Linux OpenGL Practice Chapter -14-Multi-instance rendering

Source: Internet
Author: User

Multi-Instance rendering

OpenGL's multi-instance rendering is a way to execute multiple identical render commands consecutively, and each command produces a slightly different result, often used to render a large number of geometric objects.

Imagine a scene, such as space, where we need to render several marts planets, and if we use the conventional approach, the rendering process should be: Draw the first planet Glbindvertexarray--gldrawarrays or Gldrawelements, Then use the same process to draw the other planets. However, this approach is very easy to achieve the computer performance bottleneck, even if the object is the simplest to render the most simple patch, because in the whole process of drawing, the time of the object is actually very short, and the rendering of the object preparation work time is relatively long, That is, calling Glbindvertexarray and gldrawarrays work, such as preparing vertex data, specifying which buffer the GPU reads from, where the GPU is looking for vertex properties, and so on, and that's done on the CPU-to-GPU bus (Cpu-gpu bus), As a result, GPU rendering is fast enough, but invoking too many drawing instructions can affect rendering efficiency.

The multi-instance rendering of OpenGL is intended for this scenario. Based on the above, we know that to improve rendering efficiency, the key is to reduce the invocation of OpenGL API drawing instructions. Based on this idea, we can transfer as many vertex data as possible in one drawing instruction, reducing the call of drawing instruction, that is, transmitting data once can draw multiple objects. This is the complete function of multi-instance rendering in OpenGL.

The most basic two rendering APIs for OpenGL multi-instance rendering are gldrawarraysinstanced and gldrawelementsinstanced. Other APIs, such as Gldrawarraysinstancedbaseinstance, can be thought of as being implemented based on these two APIs.

Compare the following gldrawarrays and gldrawarraysinstanced:

void Gldrawarrays (Glenum mode, glint first, glsizei count);

void Gldrawarrays (Glenum mode, glint first Glsizei count, Glzsizei primcount);

Gldrawarraysinstanced has one more primcount parameter, that is, the number of render instances. When OpenGL executes this function, it actually executes gldrawarrays primcount copies, each time the Mode,first,count is directly passed in.

Let's look at a simple example of multi-instance rendering:

       Glclear (Gl_color_buffer_bit |  Gl_depth_buffer_bit);       Glbindvertexarray (VAO);       Dshader, use ();       Gldrawarraysinstanced (gl_triangles,0,6,ten);         

Generating vertex array objects and cache objects as usual, the key is the gldrawarraysinstanced call, where we pass in 10 to draw 10 instances.

Here is the vertex shader:

#version theCorelayout ( location=0)inchvec3 ipos;layout ( location=1)inchvec3 icolor;uniform mat4 model;uniform mat4 view;uniform mat4 proj; outVEC4 Fcolor;voidMain () {Fcolor= Vec4 (Icolor,1); VEC3 POS=IPos; POS= pos + VEC3 (0.1,0.2f,-0.1) *Gl_instanceid; Gl_position= proj * View * model * VEC4 (POS,1);} 

The key to this shader is Gl_instanceid, the built-in variable, which is an integer representing the current number of instances, counting from 0. Gl_instanceid is always present in the vertex shader, even if no multi-instance rendering is used, at which point it has a value of 0. So in the vertex shader you can use Gl_instanceid to index, referencing some uniform array elements. In the shader example above, we use gl_instanced to move the position of the object and make a deviation. Of course we can also pass in an array of uniform, using Gl_instanceid to refer to, as

#version theCorelayout ( location=0)inchvec3 ipos;layout ( location=1)inchvec3 icolor;uniform mat4 model;uniform mat4 view;uniform mat4 proj;uniform vec3 offset[Ten]; outVEC3 Fcolor;voidMain () {Fcolor=Icolor; VEC3 POS= IPos +Offset[gl_instanceid]; Gl_position= proj * View * model * VEC4 (POS,1.0);}

We declare an offset array, and then use the following code in the application to assign values to the offset array.

 for (int i=0;i<; + +i) {    stringstream ss;     >> i;     = Glgetuniformlocation (program, ("" "]"). c_ STR ());    GLUNIFORM2F (LOC,OFFSET.X,OFFSET.Y);}

Effect

  

Vertex properties for multiple instances

In the example above we used the offset array and the Gl_instanceid to render the instance, but the problem with this method is that the size of the array is very easy to reach the upper limit of the uniform data size. To do this, we can use another method, the vertex attribute of a multi-instance, which is similar to the normal vertex property, and the Declaration and data configuration methods in the vertex shader are exactly the same. The only difference is that the vertex property is for a single vertex, and the multi-instance vertex property is for an entity instance. The simple understanding is that the input to the vertex shader is normal when a vertex property corresponds to a vertex, and the vertex attribute of the instance is an attribute pair that share the same data with an entity (the attribute of all vertices in the entity), that is, each instance updates the data for that property once. In order to implement this function, we need a function:

Glvertexattribdivisor (gluint index,gluint divisor);

This function is used to set the vertex properties of the index index in the vertex shader how to assign values to each instance. Divisor indicates that the vertex attribute is updated once per divisor instance. If the value of divisor is 0, it indicates that the multi-instance attribute is disabled. Let's illustrate with an example of a vertex shader;

 0in1 in vec3 icolor;uniform mat4 model;uniform MAT4 view;uniform mat4 proj;  out VEC3 Fcolor; void Main () {        = icolor;         = IPos;                                                = proj * View * model * VEC4 (POS,1.0);}       

Application calls:

Glvertexattribdivisor (1,1);

This vertex shader has a icolor property, and the index is 1, which is updated once for each vertex, as normal vertex properties are understood. After calling Glvertexdisivor to set the multi-instance attribute, the Icolor property is transformed once per instance (every three vertices is a triangle). The first 1 represents the index, and the second 1 indicates that each instance updates the Icolor data once.

The effect is consistent with the above, but we don't use gl_instanceid at this time. However, one thing to note when using the instance vertex properties is that a vertex attribute data is maximum equal to one vec4, so a mat4 occupies multiple index locations, such as layout (location=1) in Mat4 m, which takes up 1,2,3,4 four positions, It is also called 4 times when using GLUNIFORM4FV. Such as:

//Vertex Buffer ObjectUnsignedintBuffer;glgenbuffers (1, &buffer); Glbindbuffer (gl_array_buffer, buffer); Glbufferdata (Gl_array_buffer, amount*sizeof(GLM::MAT4), &modelmatrices[0], gl_static_draw); for(unsignedinti =0; I < rock.meshes.size (); i++) {unsignedintVAO =Rock.meshes[i].    VAO;    Glbindvertexarray (VAO); //Vertex PropertiesGlsizei vec4size =sizeof(GLM::VEC4); Glenablevertexattribarray (3); Glvertexattribpointer (3,4, Gl_float, Gl_false,4* Vec4size, (void*)0); Glenablevertexattribarray (4); Glvertexattribpointer (4,4, Gl_float, Gl_false,4* Vec4size, (void*) (vec4size)); Glenablevertexattribarray (5); Glvertexattribpointer (5,4, Gl_float, Gl_false,4* Vec4size, (void*)(2*vec4size)); Glenablevertexattribarray (6); Glvertexattribpointer (6,4, Gl_float, Gl_false,4* Vec4size, (void*)(3*vec4size)); Glvertexattribdivisor (3,1); Glvertexattribdivisor (4,1); Glvertexattribdivisor (5,1); Glvertexattribdivisor (6,1); Glbindvertexarray (0);} 

This section of code refers to: https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/10%20Instancing/

Source code for this practice: Https://github.com/xin-lover/opengl-learn/tree/master/chapter-13-geometryshader

Linux OpenGL Practice Chapter -14-Multi-instance rendering

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.