OpenGL Transform feed back particle system

Source: Internet
Author: User

The pipeline of the original OpenGL rendering did not provide much interface, and it was difficult to draw the process to modify the assembled elements after the draw function was called. However, there is a need for this in the drawing process, especially if the subsequent operations are updated based on the previously assembled elements. As a simple example, when there are two relatively moving objects in a scene, the latter object needs to determine its trajectory based on the movement of the previous object, so a feed back is needed to enhance the interactivity. Transform feed back is such an effective mechanism, Transform feed back after the vertex is processed, the elements are assembled and rasterized before the programmer to provide an interface. The main use of a feed back cache to return the state of the previous vertex, in the next process can be based on vertex information to effectively calculate the next motion trajectory.

The Transform feed back cache, like other caches, also has a specific function to manage. First, using Glgentransformfeedbacks to create a feed back array, which contains the ID number used to manage the corresponding feed back, it is important to note that the corresponding object is not created when the ID number is created. The creation of an object is not created until it is bound. The binding operation is done by Glbindtransformfeedback, which implements the creation of the feed back object, binds the object to the corresponding ID number, and activates the corresponding object if the ID number already exists. The OGL also provides a function to determine whether the feed back object exists and clears the object, both of which are done by the Glistransformfeedback and gldeletetransformfeedbacks two functions.

After creating and binding the feed back object, you need to submit the memory cache to the feed, and be aware that the feed back simply provides an interface that itself does not generate memory. Similar to vertex queues, the memory support behind it needs to be provided by other types of caches. There are two ways to bind the memory behind the feed back, and the first is glbindbufferbase, which will treat the target as an array, based on the target number of the supplied feed's callback object. At the same time, the memory in buffer corresponds to all the memory in the array starting with index. Another function is Glbindbufferrange, the function is similar to glbindbufferbase, the only difference is to use buffer as an array, just buffer+offset to buffer+offset+ The memory of the size area is used for the feed back.

In front of the main talk about the feed back of the object management and caching support, however, the feed back has not been associated with the specific vertex information, then how to associate and return the corresponding property values? This requires the use of the Gltransformfeedbackvaryings function, which is prototyped as follows:

void Gltransformfeedbackvaryings Program ? count?, const char * *varyings? buffermode?);
where program and the corresponding renderer are managed, and count is used to indicate how many feed back variables need to be out of the interface with the feed back object, Varyings provides the function with the name of the variable that needs to be drawn out of the interface, and the last parameter for managing the variable exists in the feed The mode in the back cache is that multiple variables appear alternately in the feed back cache, and the other is to associate a corresponding feed back cache object for each variable. It is important to note that the feed back and program are corresponding, when the program switching occurs along with the feed back queue transformation.

Once the variables have been associated with the feed back cache object, you can start to enable the transform feature and pass the feedback data to the programmer. The commands for manipulating the feed back include begin,pause,resume and end. The following is an example of red book on the "Particle system" to explain in detail the application of the transform feed back mechanism.

The particle system consists of two parts, part of which is the main goal rendering, and the second part realizes the particle update. The position of the particle and the velocity may be offset relative to the target being rendered. In order to effectively establish a connection between the two, the program uses the transform feed back to achieve the offset of the particle relative to the target. First let the particle and the target in two different space, we use a set of rendering language to get the world coordinates of the target and the final human eye coordinates.

        "#version 410\n"        "Uniform mat4 model_matrix;\n" "        uniform mat4 projection_matrix;\n"        "layout (location = 0) In Vec4 position;\n "" Layout (location = 1) in VEC3 normal;\n "" Out Vec4 world_space_position;\n "        " Out vec3 vs_fs_n "        ormal;\n "        " void main (void) \ n "        " {\ n "        "    vec4 pos = (Model_matrix * (Position * VEC4 (1.0, 1.0, 1.0, 1.0))); \ N "        "    world_space_position = pos;\n "        "    Vs_fs_normal = Normalize ((Model_matrix * VEC4 (Normal, 0.0)) . xyz); \ n "        "    gl_position = Projection_matrix * pos;\n "        "}\n ";
The vertex coordinates of the rendered language are as shown above. Where World_space_position returns the world coordinates of the target, and gl_position is used to represent the coordinates in the final human eye space. The relative motion of a particle is determined by its relative position in world coordinates, so the world coordinate system needs to be fed back to the programmer, and the programmer needs to pass this part into the particle's drawing process. To capture this feedback, you need to set the corresponding feed back. The code is as follows:

static const char * varyings2[] =    {        "world_space_position"    };    Gltransformfeedbackvaryings (Render_prog, 1, VARYINGS2, gl_interleaved_attribs);
In this step, the target is associated with the corresponding feed back object, in the subsequent drawing process can be used to return to the target vertex information, the drawing process is as follows:

    Glbindbufferbase (gl_transform_feedback_buffer, 0, Geometry_vbo);    Glbegintransformfeedback (gl_triangles);//start accepting the return information of the triangle redraw    object. Render ();    Glendtransformfeedback ();
As you can see from the code, the corresponding feed back cache is ultimately supported by GEOMETRY_TBO. Further backtracking can be found that GEOMETRY_TBO is a texture cache and has been allocated memory by OGL but not initialized. The initialization of the texture cache consists of two parts, the first part includes generating the buffer object Geometry_vbo, allocating memory for the object, and the second step creating the Geometry_tbo object and associating it with GEOMETRY_VBO. It is important to note that subsequent operations on the texture cache are based on the Geometry_tex object after the Glbindtexture function call.
    Glgenbuffers (1, &GEOMETRY_VBO);    Glgentextures (1, &geometry_tex);    Glbindbuffer (Gl_texture_buffer, GEOMETRY_VBO);    Glbufferdata (Gl_texture_buffer, 1024x768 * 1024x768 * sizeof (VMATH::VEC4), NULL, gl_dynamic_copy);    Glbindtexture (Gl_texture_buffer, Geometry_tex);    Gltexbuffer (Gl_texture_buffer, gl_rgba32f, Geometry_vbo);
The following is a discussion of the updated part of the particle system code, meaning the same distribution is no longer specifically analyzed. First look at the code for the vertex shader section.

    static const char update_vs_source[] = "#version 410\n" "Uniform mat4 model_matrix;\n" "Uniform mat4 projection_matrix;\n" "Uniform int triangle_count;\n" "Layout (location = 0) in vec4 position;\n" "Layout (lo cation = 1) in vec3 velocity;\n "off Vec4 position_out;\n" "Out VEC3 velocity_out;\n" "Uniform Sampl Erbuffer geometry_tbo;\n "" Uniform float Time_step = 0.02;\n "" bool Intersect (VEC3 origin, vec3 dire ction, vec3 V0, VEC3 v1, VEC3 v2, out VEC3 point) \ n "" {\ n "" Vec3 u, V, n;\n "" Vec 3 W0, w;\n "" Float R, a, b;\n "\ n" "U = (v1-v0); \ n" "V = (V2- V0) \ n "" N = Cross (U, v); \ n "\ n" "W0 = origin-v0;\n" "A = Dot (n  , w0); \ n "//ori the distance from point to plane" b = dot (n, direction); \ n "//The distance between the motion direction and the plane" \ n "" R = a/b;\n "" If (R < 0.0 | |        R > 1.0) \ n ""return false;\n "\ n" "point = Origin + R * direction;\n" \ n "" Float UU, UV, VV, Wu, WV, d;\n "\ n" uu = Dot (u, u); \ n "" UV = dot (u, v); \ n "" VV = dot (V, v); \ n "" W = point-v0;\n "" Wu = Dot (w, u); \ n "" WV = dot ( W, v); \ n "" "D = UV * Uv-uu * vv;\n" "\ n" "Float s, t;\n" \ n "" s = (UV * WV-VV * wu)/d;\n "" if (S < 0.0 || s > 1.0) \ n "" "Return false;\n" "T = (UV * WU-UU * WV)/d;\n" "if (T < 0.0 | |            (S + t) > 1.0) \ n "" Return false;\n "\ n" "Return true;\n" "}\n" "\ n"            "Vec3 Reflect_vector (vec3 V, vec3 n) \ n" "{\ n" "Return v-2.0 * dot (V, N) * n;\n" "}\n" "\ n" "Void Main (void) \ n" "{\ n" "Vec3 accelleration = vec3 (0.0,-0.3 , 0.0); \ n "" vec3 new_velocity = velocity + accelleration * time_step;\n "" Vec4 new_position = position + VEC4 (new_velocity * time_step, 0.0) \ n "" "Vec3 V0, V1, v2;\n" "Vec3 point;\n" "int i;\n" "for ( i = 0; i < Triangle_count; i++) \ n "" {\ n "" V0 = Texelfetch (Geometry_tbo, I * 3). xyz;\n "" V1 = Tex         Elfetch (GEOMETRY_TBO, I * 3 + 1). xyz;\n "" v2 = Texelfetch (GEOMETRY_TBO, I * 3 + 2). xyz;\n ""            if (Intersect (POSITION.XYZ, new_position.xyz-position.xyz, V0, V1, v2, point)) \ n "" {\ n " "Vec3 n = Normalize (cross (v1-v0, v2-v0); \ n" "new_position = VEC4 (point + ref Lect_vector (New_position.xyz-point, N), 1.0); \ n "" new_velocity = 0.8 * Reflect_vector (new_velocit    Y, n); \ n "" "}\n" "}\n" "if (New_position.y < -40.0) \ n" "   {\ n "" new_position = VEC4 (-new_position.x * 0.3, POSITION.Y + 80.0, 0.0, 1.0); \ n ""     New_velocity *= VEC3 (0.2, 0.1, -0.3); \ n ""}\n "" velocity_out = new_velocity * 0.9999;\n "" Position_out = new_position;\n "" Gl_position = Projection_matrix * (Model_matrix * Positi on); \ n ""}\n ";
In the vertex shader language, you first need to find the part associated with the rendered part-the data of the world coordinate system received. After the Glbindtexture function call is mentioned above, the manipulation of the texture is based on GEOMETRY_TBO. A texture cache is also defined in the vertex shader language, except that the definition is implemented by a built-in variable declaration, and the type of the variable is samplerbuffer. Once defined, the ability to access the texture cache through the vertex shader is implemented. During execution, the built-in function Texelfetch gets the vertex information in the texture cache, and three vertices are combined into one basic entity-the triangle. After the vertex information is obtained, it is necessary to determine whether the particle intersects with the three-vertex triangle area. To determine whether the intersection is implemented by the Intersect function, the function first determines whether the current point intersects a plane consisting of three vertices. First of all, the point as a ray, if the point on the plane to the beginning and beginning to the end of the angle is obtuse, then its direction of movement is far away from the plane, so the two symbols are the opposite, so A/b is less than 0, conversely, when the angle of the two is a sharp angle to determine whether the distance is enough to reach When B is greater than 1, no contact occurs on the same plane. After the above operation, only the ray and the plane intersect, we have to judge not only whether to intersect but also to determine whether the focus is within the Triangle area. Next, update the contact points for lines and polygons. and determine whether the point is within the triangle. The Judgment method uses the V0 as the starting point, uses the V0 to the V1, and V0 to the V2 to combine, the concrete derivation process reference webpage http://www.cnblogs.com/graphics/archive/2010/08/05/1793393.html.

If a collision occurs, the particle is reflected out using the reflection principle, which is implemented by Reflect_vector.

V-dot (V, N) * n <span style= "font-family:arial, Helvetica, Sans-serif;" > </span><span style= "font-family:arial, Helvetica, Sans-serif;" >-  * DOT (V, N) * n</span>

The first minus breaks the velocity v into the normal vector n direction of motion, and the second minus moves the direction of motion. Next you need to set the next motion speed and position of the captured particles.

    static const char * varyings[] =    {        "position_out", "Velocity_out"    };//used to capture the location information and speed information    of the example Gltransformfeedbackvaryings (Update_prog, 2, varyings, gl_interleaved_attribs);
Next the vertex information is generated, there are two sets of vertex information, the first set is used to submit the current vertex information to the OGL, and the other is used to return the vertex information returned by the feed back function.

    Glgenvertexarrays (2, Vao);    Glgenbuffers (2, VBO);        for (i = 0; i < 2; i++) {Glbindbuffer (Gl_transform_feedback_buffer, vbo[i]); Glbufferdata (Gl_transform_feedback_buffer, Point_count * (sizeof (VMATH::VEC4) + sizeof (VMATH::VEC3)), NULL, Gl_        Dynamic_copy);                if (i = = 0) {struct buffer_t {vmath::vec4 position;            VMATH::VEC3 Velocity;            } * buffer = (buffer_t *) Glmapbuffer (Gl_transform_feedback_buffer, gl_write_only);                for (j = 0; J < Point_count; J + +) {buffer[j].velocity = Random_vector ();                Buffer[j].position = VMATH::VEC4 (buffer[j].velocity + vmath::vec3 ( -0.5f, 40.0f, 0.0f), 1.0f);            buffer[j].velocity = VMATH::VEC3 (Buffer[j].velocity[0], buffer[j].velocity[1] * 0.3f, buffer[j].velocity[2] * 0.3f);        } glunmapbuffer (Gl_transform_feedback_buffer);        } glbindvertexarray (Vao[i]); Glbindbuffer (Gl_arRay_buffer, Vbo[i]);//The data in the BUFFER array is stored in the vertex sequence glvertexattribpointer (0, 4, gl_float, Gl_false, sizeof (VMATH::VEC4)        + sizeof (VMATH::VEC3), NULL); Glvertexattribpointer (1, 3, gl_float, Gl_false, sizeof (VMATH::VEC4) + sizeof (VMATH::VEC3), (glvoid *) sizeof (Vmath::        VEC4));        Glenablevertexattribarray (0);    Glenablevertexattribarray (1); }
Finally, the process of particle drawing.

    if ((Frame_count & 1)! = 0)    {        glbindvertexarray (vao[1]);        Glbindbufferbase (gl_transform_feedback_buffer, 0, vbo[0]);    }    else    {        glbindvertexarray (vao[0]);        Glbindbufferbase (gl_transform_feedback_buffer, 0, vbo[1]);    }    Glbegintransformfeedback (gl_points);    Gldrawarrays (gl_points, 0, Min (point_count, (Frame_count >> 3)));    Glendtransformfeedback ();
Last one.

OpenGL Transform feed back particle system

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.