GLSL(2)记录-使用uniform block

来源:互联网 发布:淘宝虚拟对话生成器 编辑:程序博客网 时间:2024/05/22 07:42
#include <iostream>#include"shadertool.h"#include"glm/glm.hpp"//using namespace std;#include"glm/gtc/matrix_transform.hpp"using glm::mat4;using glm::vec3;#define PI 3.1415926GLuint vaoHandle;GLuint programHandle;float angle = 30.0f * PI/180.0f;//转换为弧度制void InitUniformBlockBuffer();//we create and populate the vertex buffer objects for each attributefloat positionData[] = {    -0.8f, -0.8f, .0f,    0.8f, -0.8f, 0.0f,    0.8f, 0.8f, 0.0f,    -0.8f,-0.8f,0.0f,    0.8f,0.8f,0.0f,    -0.8f,0.8f,0.0f};//上面的六个点刚好形成一个正方形//三角形三个顶点,每个顶点的RGBfloat colorData[] = {    1.0f, 0.0f, 0.0f,    0.0f, 1.0f, 0.0f,    0.0f, 0.0f, 1.0f};//正方形四个顶点,每个顶点的RGBfloat tcData[] ={    .0f,.0f,1.0f,    .0f,1.0f,1.0f,    .0f,.0f,1.0f,    1.0f,.0f,1.0f};void changeSize(int w,int h){    if(h==0)    {        h=1;    }    float ratio=1.0*w/h;    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    glViewport(0,0,w,h);    gluPerspective(45,ratio,1,1000);    glMatrixMode(GL_MODELVIEW);}void renderScene(void){    glClear(GL_COLOR_BUFFER_BIT);    glBindVertexArray(vaoHandle);    glDrawArrays(GL_TRIANGLES,0,6);//shader必须依附在一个物体上才能体现出来,unity里面也不能直接看shader效果    //一般都需要给一个cube或者sphere一个带某种shader的材质才能出现效果。这里也一样,这里是把shader效果依附到两个    //三角形上面(6个顶点),两个三角形是6个顶点,构成的正方形是4个顶点,注意这里要写三角形顶点的总数量    glutSwapBuffers();}void processNormalKeys(unsigned char key,int x,int y){    if(key==27)    {        exit(0);    }}void setShaders(){    char* vs_code = LoadShaderFromFile("shader//uniform_block.vert");    char* fs_code = LoadShaderFromFile("shader//uniform_block.frag");    GLuint v = glCreateShader(GL_VERTEX_SHADER);//create shader obj,返回一个handle    GLuint f = glCreateShader(GL_FRAGMENT_SHADER);    const char* ff = fs_code;    const char* vv = vs_code;    /*    load the source code into shader obj,第三个参数可以是一个字符串数组,可以载入多个文件string    第二个参数是表示string array 的size,one string ,so 1.    最后一个参数表示each source code string is terminated by a null character.    一旦这个函数返回后,表明source code 已经被成功加载在opengl的内部内存,因此,之前的用来存储shader code的字符串变量    可以被释放掉了    */    glShaderSource(v,1,&vv,NULL);    glShaderSource(f,1,&ff,NULL); //    //free the source code    free(vs_code);    free(fs_code);    //next step:    //compile shader and log error    CompileShader(v,0);    CompileShader(f,1);    //final step : shaders must be linked togehter into a shader program object.    programHandle = glCreateProgram();//create a empty program obj    glAttachShader(programHandle,f);    glAttachShader(programHandle,v);    //link.can use glGetProgramiv to query status(GL_TRUE/GL_FALSE)->glGetProgramiv(GL_LINK_STATUS)    glLinkProgram(programHandle);    //install the program into the opengl pipeline    glUseProgram(programHandle);}void InitUniformBlockBuffer(){    GLuint blockIndex = glGetUniformBlockIndex(programHandle,"BlobSettings");    GLint blockSize;    glGetActiveUniformBlockiv(programHandle,blockIndex,GL_UNIFORM_BLOCK_DATA_SIZE,&blockSize);    GLubyte* blockBuffer;    //allocate a temporary buffer to hold the data for our block    blockBuffer = (GLubyte*)malloc(blockSize);    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);    //place the data into the buffer at the appropriate offsets:    GLfloat outerColor[] = {.0f, .0f, .0f, .0f};    GLfloat innerColor[] = {1.0f, 1.0f, .7f, .7f};    GLfloat innerRadius = 0.1f, outerRadius = 0.45f;    memcpy( blockBuffer + offset[0], innerColor, 4 * sizeof(GLfloat));    memcpy( blockBuffer + offset[1], outerColor, 4 * sizeof(GLfloat));    memcpy( blockBuffer + offset[2], &innerRadius, sizeof(GLfloat));    memcpy( blockBuffer + offset[3], &outerRadius, sizeof(GLfloat));    //create the buffer object and copy the data into it    GLuint uboHandle;    //generate a buffer handle    glGenBuffers(1, &uboHandle);    //bind the buffer to the GL_UNIFORM_BUFFER binding point    glBindBuffer( GL_UNIFORM_BUFFER, uboHandle);    // copy blockBuffer's data  to GL_UNIFORM_BUFFER,we use GL_DYNAMIC_DRAW as the usage hint    //here because uniform data may be changed somewhat ofen during rendering.    glBufferData( GL_UNIFORM_BUFFER, blockSize, blockBuffer, GL_DYNAMIC_DRAW);    //finally,we associate the buffer object with the uniform block    glBindBufferBase(GL_UNIFORM_BUFFER, 0 , uboHandle);}void InitScene(int argc,char* argv[]){    //#pragma region 基本不动的代码    glutInit(&argc,argv);    //初始化glut,必须调用,复制黏贴这句话即可  //  glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT,GL_TRUE);    glEnable(GL_DEBUG_OUTPUT);    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE ); //设置显示方式,RGB、双缓冲    glutInitWindowPosition(100,100);   //位置    glutInitWindowSize(400,400);//窗口大小    glutCreateWindow("GLSL FUN!");  //创建窗口,设置标题    glutDisplayFunc(renderScene);  // 当绘制窗口时调用myDisplay    glutIdleFunc(renderScene);    glutReshapeFunc(changeSize);    glutKeyboardFunc(processNormalKeys);    //glEnable(GL_DEPTH_TEST);    glClearColor(0.0,0.0,0.0,0.0);//清除颜色设置为白色,这样glclear后面clear color就用白色clear    glewInit();    //#pragma endregion OK    //1.创建    //create and populate the buffer objects    GLuint vboHandles[2];    glGenBuffers(2, vboHandles);    GLuint positionBufferHandle = vboHandles[0];    GLuint tcBufferHandle = vboHandles[1];    //2.   // populate the position buffer    glBindBuffer( GL_ARRAY_BUFFER, positionBufferHandle);    glBufferData( GL_ARRAY_BUFFER, 18 * sizeof(float), positionData, GL_STATIC_DRAW);    //populate color buffer    glBindBuffer( GL_ARRAY_BUFFER, tcBufferHandle);    //最后一个参数告诉我们这个数据是用来干嘛的,static表示不能再被修改    glBufferData( GL_ARRAY_BUFFER, 12 * sizeof(float), tcData, GL_STATIC_DRAW);    //3.create and set up the vertex array objects    glGenVertexArrays(1, &vaoHandle);    glBindVertexArray( vaoHandle );    //enable the vertex attribute arrays    glEnableVertexAttribArray(0);//vertex position    glEnableVertexAttribArray(1);//vertex color    //map index 0 to the position buffer    glBindBuffer( GL_ARRAY_BUFFER, positionBufferHandle);    glVertexAttribPointer(0,3,GL_FLOAT, GL_FALSE, 0 ,NULL);    //map index 1 to the color buffer    glBindBuffer(GL_ARRAY_BUFFER, tcBufferHandle);    glVertexAttribPointer(1,2,GL_FLOAT, GL_FALSE, 0 ,NULL);    ////    glEnable(GL_BLEND);//    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);}int main(int argc,char* argv[]){    //1.    InitScene(argc,argv);    //2.    setShaders();    //after linking,use the following steps to assign data to uniform block in the frag shader    InitUniformBlockBuffer();   // LogGLVersion();     //4.    glutMainLoop();  //消息循环    //    //check gl version    return 0;}

顶点着色器:

#version 430layout (location = 0) in vec3 VertexPosition;layout (location = 1) in vec3 VertexTexCoord;out vec3 TexCoord;void main(){TexCoord = VertexTexCoord;gl_Position = vec4(VertexPosition,1.0);}
像素着色器:

#version 430in vec3 TexCoord;layout (location = 0) out vec4 FragColor;layout (binding = 0) uniform BlobSettings{vec4 InnerColor;vec4 OuterColor;float RadiusInner;float RadiusOuter;};void main(){float dx = 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));}
结果: