OpenGL (11)-data transmission in glsl4.x

Source: Internet
Author: User

In out

For vertex shader, each vertex is included once. During its main work, It processes the data about the specified point and then passes the result to the next stage of the pipeline.

In previous glsl versions, data is provided through some built-in variables, such as gl_vertex and gl_normal. However, currently, General vertex attributes (generic vertex attributes) are usually used, it is usually associated with a buffer object. For programmers, they can now define certain vertex attribute sets to provide input, as long as they useInKeyword.

Another way is to use uniform variables. The difference between such variables and attribute variables: attribute variables mean that when each vertex shader is called, the corresponding attribute values of the vertex are loaded from the vertex buffer according to the attribute position, while the uniform variable, this variable remains unchanged for each draw call, which means that you load the variable before the draw call, and the variable can be accessed when each vertex shader in the draw is executed, and the variable value remains unchanged. It can be declared in one or more shader. If it is declared in multiple shader, the types of variables must be consistent. The uniform variable is often used to store some constant data during draw execution, such as illumination parameters, change matrices, texture object handles, and so on.

The following is a modification based on the glsl example. By adding an uniform rotation variable, each vertex is rotated at a certain angle.

The first is basic. Vert:

#version 400layout (location = 0) in  vec2 in_Position;layout (location = 1) in  vec3 in_Color;out vec3 ex_Color;uniform mat4 RotationMatrix;void main(void) {     gl_Position = RotationMatrix * vec4(in_Position.x, in_Position.y, 0.0, 1.0);    ex_Color = in_Color;}

Added the four-dimensional matrix variable of uniform to store the rotation matrix.

Modify main. cpp as follows:

First, add the header file because the GLM library is used.

#include <glm/glm.hpp>#include <glm/gtc/matrix_transform.hpp>using glm::mat4;using glm::vec3;

Then modify the code in rendergl as follows:

glUseProgram(programHandle); float angle = 30; mat4 rotationMatrix = glm::rotate(mat4(1.0f), angle, vec3(0.0f,0.0f,1.0f));GLuint location =glGetUniformLocationg(programHandle,"RotationMatrix");if( location >= 0 ){glUniformMatrix4fv(location, 1, GL_FALSE,&rotationMatrix[0][0]);}//Draw a squareint i; for (i=2; i <=4; i++)    {        /* Make our background black */        glClearColor(0.0, 0.0, 0.0, 1.0);        glClear(GL_COLOR_BUFFER_BIT);        /* Invoke glDrawArrays telling that our data is a line loop and we want to draw 2-4 vertexes */        glDrawArrays(GL_TRIANGLE_FAN, 0, i);    }     // Unbind shader    glUseProgram(0);

The first part of the modification is to generate an optional matrix. glgetuniformlocation is used to check whether a variable exists, and then gluniformmatrix4fv is used to bind a value. Finally, shader can call the uniform data during painting.

Use uniform blocks and uniform buffer object

UBO, as its name implies, is a buffer object that loads uniform variable data. In terms of concept, it is similar to a buffer object such as VBO. It is an area in the display memory used to store specific data. On the OpenGL end, its creation, update, and destruction methods are no different from other buffer objects. We just give one or more uniform data to it, instead of gluniform, data is transmitted. It must be clarified that the data is stored on this UBO instead of shaderprogram, so they do not occupy the uniform storage space of this shaderprogram, therefore, UBO is a new way to transmit data, from the path to the destination, are different from the traditional uniform variable. Naturally, for such data, the shader can no longer refer to the above Code. With the introduction of UBO, glsl also introduces the uniform
Block.

The uniform block is a type of interface block. (The layout meaning is described later.) After the uniom keyword, it directly follows a block name and braces, which are one or more uniform variables. An uniform block can refer to a UBO data. We need to associate the uniform variable in the block with the data in OpenGL.

Or modify based on the above example, we need to achieve the following results

First, write a new basic. Frag

#version 400 in  vec3 texCoord;layout(location = 0) out vec4 fragColor;uniform blobSettings{vec4 innerColor;vec4 outerColor;float radiusInner;float radiusOuter;};void main(void) {    float dx = abs(texCoord.x) - 0.5;    float dy = texCoord.y -0.5;    float dist = sqrt(dx*dx + dy*dy);    fragColor = mix(innerColor, outerColor, smoothstep(radiusInner, radiusOuter, dist));}

First, define texcoord as the input from vertex shader, and then fragcolor as the output to color the pixels.

Basic. Vert is not very large, and a texture coordinate is added.

layout (location = 0) in  vec3 inPosition;layout (location = 1) in  vec3 vertexTextCoord;out vec3 texCoord;void main(void) { texCoord = vertexTextCoord;    gl_Position = vec4(inPosition, 1.0);}

In Main. C, you need to add a function to initialize UBO and bind the data in the uniform block.

void initUniformBlockBuffer(){    // Get the index of the uniform block    GLuint blockIndex = glGetUniformBlockIndex(programHandle, "blobSettings");    // Allocate space for the buffer    GLint blockSize;    glGetActiveUniformBlockiv(programHandle, blockIndex,                              GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);    GLubyte * blockBuffer;    blockBuffer = (GLubyte *) malloc(blockSize);    // Query for the offsets of each block variable    const GLchar *names[] = { "innerColor", "outerColor",                              "radiusInner", "radiusOuter" };    GLuint indices[4];    glGetUniformIndices(programHandle, 4, names, indices);    GLint offset[4];    glGetActiveUniformsiv(programHandle, 4, indices, GL_UNIFORM_OFFSET, offset);    // Store data within the buffer at the appropriate offsets    GLfloat outerColor[] = {0.0f, 1.0f, 0.0f, 0.0f};    GLfloat innerColor[] = {1.0f, 0.0f, 0.75f, 1.0f};    GLfloat innerRadius = 0.25f, outerRadius = 0.45f;    memcpy(blockBuffer + offset[0], innerColor, 4 * sizeof(GLfloat));    memcpy(blockBuffer + offset[1], outerColor, 4 * sizeof(GLfloat));    printf("Initsa VSBO!\n");    memcpy(blockBuffer + offset[2], &innerRadius, sizeof(GLfloat));    memcpy(blockBuffer + offset[3], &outerRadius, sizeof(GLfloat));    // Create the buffer object and copy the data    GLuint uboHandle;    glGenBuffers( 1, &uboHandle );    glBindBuffer( GL_UNIFORM_BUFFER, uboHandle );    glBufferData( GL_UNIFORM_BUFFER, blockSize, blockBuffer, GL_DYNAMIC_DRAW );    // Bind the buffer object to the uniform block    glBindBufferBase( GL_UNIFORM_BUFFER, blockIndex, uboHandle );}

The shader initialization function also needs to be modified:

void initShader(){ /* We're going to create a square made from lines */ const GLfloat positionData[4][3] = {      {  -1.0,  1.0, 0.0   }, /* Top point */      {  1.0,  1.0, 0.0  }, /* Right point */      {  1.0, -1.0, 0.0  }, /* Bottom point */      { -1.0,  -1.0, 0.0  } }; /* Left point */          float tcData[] = {        0.0f, 0.0f,        1.0f, 0.0f,        1.0f, 1.0f,        1.0f, 0.0f,        1.0f, 1.0f,        0.0f, 0.0f    };     /* These pointers will receive the contents of our shader source code files */    GLchar *vertexsource, *fragmentsource;     /* These are handles used to reference the shaders */    GLuint vertexshader, fragmentshader;     /* This is a handle to the shader program */    GLuint shaderprogram;         /* Allocate and assign a Vertex Array Object to our handle */    glGenVertexArrays(1, &vao);     /* Bind our Vertex Array Object as the current used object */    glBindVertexArray(vao);     /* Allocate and assign two Vertex Buffer Objects to our handle */    glGenBuffers(2, vbo);     /* Bind our first VBO as being the active buffer and storing vertex attributes (coordinates) */    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);        glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), positionData, GL_STATIC_DRAW);          /* Specify that our coordinate data is going into attribute index 0, and contains two floats per vertex */    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);     /* Enable attribute index 0 as being used */    glEnableVertexAttribArray(0);     /* Bind our second VBO as being the active buffer and storing vertex attributes (colors) */    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);        glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), tcData, GL_STATIC_DRAW);     /* Specify that our color data is going into attribute index 1, and contains three floats per vertex */     glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);     /* Enable attribute index 1 as being used */    glEnableVertexAttribArray(1);vShader = glCreateShader( GL_VERTEX_SHADER );fShader = glCreateShader( GL_FRAGMENT_SHADER );printf("Here\n");if(0 == vShader || 0 == fShader){fprintf(stderr, "Error creating vertex shader.\n");quit(1);}GLchar* vShaderCode = textFileRead("basic.vert");GLchar* fShaderCode = textFileRead("basic.frag");const GLchar* vCodeArray[1] = {vShaderCode};const GLchar* fCodeArray[1] = {fShaderCode};glShaderSource(vShader, 1, vCodeArray, NULL);glShaderSource(fShader, 1, fCodeArray, NULL);glCompileShader(vShader);glCompileShader(fShader);free(vShaderCode);free(fShaderCode);GLint result;glGetShaderiv( vShader, GL_COMPILE_STATUS, &result );if( GL_FALSE == result ){fprintf( stderr, "Vertex shader compilation failed!\n" );GLint logLen;glGetShaderiv( vShader, GL_INFO_LOG_LENGTH, &logLen );if( logLen > 0 ){char * log = (char *)malloc(logLen);GLsizei written;glGetShaderInfoLog(vShader, logLen, &written, log);fprintf(stderr, "Shader log:\n%s", log);free(log);}}programHandle = glCreateProgram();if(0 == programHandle){fprintf(stderr, "Error creating programHandle.\n");quit(1);}glAttachShader(programHandle, vShader);glAttachShader(programHandle, fShader);glBindAttribLocation(programHandle, 0, "in_Position");glBindAttribLocation(programHandle, 1, "in_Color");glLinkProgram(programHandle);}

Draw a square directly during rendering.

glUseProgram(programHandle);glDrawArrays(GL_QUADS,0,4);glUseProgram(0); 

Compile command

G ++ main. C-o main-l SDL-lgl-lglu-lglut-lglew

* Shader debugging tips

Since printing statements cannot be used in the shader, it may be a bit difficult to debug the shader. We can use the glget method to obtain some state variables to judge the shder status, more commonly used is to change the shader code and then debug it using the rendering results. For example:

void main(){  float bug=0.0;  vec3 tile=texture2D(colMap, coords.st).xyz;  vec4 col=vec4(tile, 1.0);  if(something) bug=1.0;  col.x+=bug;  gl_FragColor=col;}

 

Code download

Write a C ++ shader class

First, you need to upgrade the glew library of the system. Many features of the old version glew4.x are not supported.

Go to http://glew.sourceforge.net/download the latest version 1.10, decompress the cdns into the directory, and run:

Make

Sudo make install

The basic knowledge of glsl has been almost reached by now. For more convenience, we now encapsulate shader into a class and add it to the previous framework.

The code will not be pasted. Click here to download it.

Reference

OpenGL/glsl data transfer note (3.x)-http://www.zwqxin.com/archives/shaderglsl/communication-between-opengl-glsl-2.html

OpenGL 4.0 shading language cookbook

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.