Draw a Circle in Opengl Using Shaders
In the previous affiliate the basics of using a shader to render simple primitives were introduced. This affiliate introduces bones usage of the fragment shader. In particular, this affiliate shows a few things that can exist done in fragment shaders using one the nearly basic congenital-in inputs and functions. After chapters will build on these examples.
Drawing Circles Using                              gl_FragCoord                          
                            It would seem that a fragment shader such as 	Effigy�two, "Simple fragment shader" would have no inputs when paired with a 	vertex shader such as Effigy�1, "Uncomplicated vertex shader".  Even so, every 	fragment shader has at least one built-in input:  the current fragment 	position.  The variable                      gl_FragCoord                    contains 	the window position of the current fragment in its X and Y 	components.  The Z component contains fragment's depth value on the 	range [0, 1].        
Figure�1.�Simple vertex shader
                ane void master(void)  2 {  three     gl_Position = gl_Vertex;  4 }                          Figure�2.�Simple fragment shader
                i void main(void)  2 {  3     gl_FragColor = vec4(0.0, one.0, 0.0, 1.0);  4 }                                    The fragment shader in Figure�three, "Circle fragment shader" 	uses                      gl_FragCoord                    to return a simple pattern. 	The shader partitions the window into l-by-50 pixel squares.  Line 3 	in the shader computes the position of the current fragment relative 	to the center of the 50-by-50 pixel region that contains it.  Line 4 	computes the squared distance from the center.  Lines 6 through viii use 	that distance to write either greyness or blue 	to                      gl_FragColor          .  The leftmost image of 	Figure�iv, "Output of circumvolve fragment shader" is a sample paradigm rendered by this 	shader.  The upshot is a series of 20 pixel diameter greyness circles.        
Figure�iii.�Circle fragment shader
                1 void principal(void)  ii {  3     vec2 pos = mod(gl_FragCoord.xy, vec2(50.0)) - vec2(25.0);  four     bladder dist_squared = dot(pos, pos);  5   6     gl_FragColor = (dist_squared < 400.0)   7         ? vec4(.90, .xc, .ninety, one.0)  viii         : vec4(.20, .20, .40, 1.0);  9 }                          Figure�4.�Output of circumvolve fragment shader
                
              
                
              
                
              
                From left to right: Epitome produced without interpolation of colors. 	  Image produced using                linearstep.  Image 	  produced using                smoothstep.              
          The shader in Figure�3, "Circle fragment shader" can be rewritten to 	utilize 2 useful functions that are built into GLSL. 	The          footstep          function returns 0.0 for each component 	of                      value                    that is less 	than                      edge          .        
genType step(genType edge, genType value); genType step(float edge, genType value);
          Like many functions in GLSL,          step          has parameters 	and render values with the type          genType.  This is 	shorthand for          float,          vec2,          vec3, and          vec4.  The total 	set of overloaded versions of          step          is:        
float step(float edge, float value); vec2 step(vec2 edge, vec2 value); vec3 step(vec3 edge, vec3 value); vec4 step(vec4 edge, vec4 value); vec2 step(float edge, vec2 value); vec3 stride(float edge, vec3 value); vec4 pace(bladder edge, vec4 value);
          The          mix          role calculates the component-wise 	linear interpolation of                      v0                    and                      v1                    using                      t                    as the 	blend factor.  More precisely,          mix          computes          
genType mix(genType v0, genType v1, genType t); genType mix(genType v0, genType v1, float t);
          Using          stride          and          mix          the 	shader in Figure�3, "Circle fragment shader" can be rewritten as the 	shader in Effigy�5, "Circumvolve fragment shader using          mix          and          stride".  Both shaders should 	produce identical output.        
              Figure�five.�Circumvolve fragment shader using                mix                and                step                          
                1 void main(void)  2 {  3     vec2 pos = mod(gl_FragCoord.xy, vec2(fifty.0)) - vec2(25.0);  4     float dist_squared = dot(pos, pos);  5   6     gl_FragColor = mix(vec4(.90, .90, .90, i.0), vec4(.20, .xx, .xl, 1.0),  7                        stride(400.0, dist_squared));  eight }                                    A close examination of the leftmost Figure�4, "Output of circumvolve fragment shader" 	reveals an unpleasant sharp boundary at the edge of the circle.  In 	this implementation, each pixel is either greyness or blue.  The exact 	edge of a 20 pixel radius circle actually passes through a different 	portion of each pixel along the edge.  Equally a consequence, pixels along the 	border should be fatigued with some combination of blue and grayness.  The can 	be acomplished by adjusting the 3rd parameter to 	the          mix          function.        
          If the distance from the centre is below some threshold, say 19.five, the 	pixel should exist completely greyness.  If the distance from the eye is 	higher up another threshold, say 20.5, the pixel should be completely 	blueish.  If the distance between these two thresholds, the pixel should 	exist some combination of blue and gray.  This new blend factor could be 	implemented as in Effigy�six, "linearstep          function". 	Using          linearstep          in identify 	of          pace          in Figure�5, "Circle fragment shader using          mix          and          footstep" 	results in the center image in Figure�4, "Output of circle fragment shader".        
              Effigy�vi.�linearstep                role            
                1 bladder linearstep(float lo, float hullo, bladder 10)  2 {  3     return (clamp(x, lo, hi) - lo) / (howdy - lo);  4 }                                    Notice that the edges have gone from likewise sharp to too blury.  Instead 	of a simple linear interpolation, an interpolator that change slowly 	near the edges and quickly through the middle will produce better 	results.  The Hermite interpolator,          smoothstep, which 	computes this value over a given 	range.          linearstep          can exist directly replaced 	with          smoothstep          to produce the rightmost epitome in 	Figure�4, "Output of circle fragment shader".  The last shader appears in 	Effigy�7, "Circumvolve fragment shader using          mix          and          smoothstep".        
genType smoothstep(genType low_edge, genType high_edge, genType value); genType smoothstep(float low_edge, float high_edge, genType value);
              Figure�7.�Circle fragment shader using                mix                and                smoothstep                          
                1 void main(void)  ii {  3     vec2 pos = mod(gl_FragCoord.xy, vec2(l.0)) - vec2(25.0);  4     bladder dist_squared = dot(pos, pos);  5   six     gl_FragColor = mix(vec4(.ninety, .90, .ninety, one.0), vec4(.20, .twenty, .xl, 1.0),  seven                        smoothstep(380.25, 420.25, dist_squared));  8 }                          
Rotated Circles
          Since                      gl_FragCoord                    is just a two-dimensional 	coordinate, transformations can be applied to it.  Using a unproblematic 	coordinate transformation, every bit in 	Effigy�eight, "Rotated circle fragment shader", the orientation of the circles 	can be changed.  The output of this shader is shown in 	Figure�9, "Output of rotated circle fragment shader".  The matrix used in the shader 	may non wait like the usual rotation matrix.  Matrices in OpenGL are 	typically column-major.  The start two elements of this matrix 	represent the first column of the matrix.        
Figure�viii.�Rotated circle fragment shader
                1 #define M_PI iii.14159265358979323846  2   3 const mat2 rotation = mat2( cos(M_PI/4.0), sin(M_PI/four.0),  4                            -sin(M_PI/4.0), cos(M_PI/4.0));  five void chief(void)  6 {  seven     vec2 pos = mod(rotation * gl_FragCoord.xy, vec2(50.0)) - vec2(25.0);  8     float dist_squared = dot(pos, pos);  ix  10     gl_FragColor = mix(vec4(.90, .90, .90, ane.0), vec4(.20, .20, .40, i.0), 11                        smoothstep(380.25, 420.25, dist_squared)); 12 }                          Figure�9.�Output of rotated circle fragment shader
                
              
There is i big disadvantage of the shader in Effigy�viii, "Rotated circle fragment shader". If the application wants to change the rotation bending, it has to change the shader source. A later chapter will bear witness a method for passing parameters into shaders that are constant across a group of primitives.
Cut Holes
          Occasionally it is useful to take "holes" in the rendered image.  A 	special fragment shader keyword          discard          tin can do 	this.  In lines 6 and 7 of Figure�10, "Circumvolve fragment shader using          discard" 	compare the squared radius to the range [100, 575].  Any fragments 	outside that range are discarded[one].  In Effigy�eleven, "Output of circle fragment shader that 	uses          discard" the black 	pixels are the background color.  This shows through where fragments 	are discarded.        
              Figure�10.�Circumvolve fragment shader using                discard                          
                1 void main(void)  two {  3     vec2 pos = modern(gl_FragCoord.xy, vec2(50.0)) - vec2(25.0);  4     bladder dist_squared = dot(pos, pos);  5   half-dozen     if ((dist_squared > 575.0) || (dist_squared < 100.0))  seven             discard;  8   9     gl_FragColor = mix(vec4(.xc, .ninety, .90, 1.0), vec4(.20, .20, .40, ane.0), 10                        smoothstep(380.25, 420.25, dist_squared)); xi }                                        Effigy�xi.�Output of circle fragment shader that 	uses                discard                          
                
              
          It is tempting the think of          discard          as analogous 	to calling          exit          in a C programme.  Consider the 	code in Figure�12, "Shader with a possible infinite loop".  Lines 2 and 3 discard the 	fragment if the variable                      x                    is less than some 	pocket-sized value.  Lines 5 through seven loop using                      10                    as 	a loop control.  If                      x                    is very pocket-sized or zero, 	the number of loop iterations is very large or infinite.        
Figure�12.�Shader with a possible infinite loop
                1     /* If x is less than ane/32nd, get out. */  ii     if (x < 0.03125)  three         discard;  4   5     for (int i = 0; i < int(1.0 / 10); i++) {  6         /* ... do some work ... */  7     }                                    Lines 2 and three are designed to terminate the shader to prevent this 	from occuring.  Hardware typically runs fragment shaders on small-scale 	blocks of fragments, ordinarily 2x2, together.  If one fragment in a group 	does not execute the          discard, all of the fragments 	in the may continue executing.  The shader may enter an space loop 	even though the programmer has attempted to foreclose it.  The solution 	is to surround the remainder of the shader in 	the          else          portion of 	the          if-statement.        
Source: https://people.freedesktop.org/~idr/OpenGL_tutorials/03-fragment-intro.html
0 Response to "Draw a Circle in Opengl Using Shaders"
Postar um comentário