实现程序:
#include "stdafx.h"#include<iostream>using namespace std;#include "vgl.h"#include "LoadShaders.h"//uniform//在着色器运行之前,uniform修饰符可以指定一个在应用程序中设置好的变量,它不会在图元处理的过程中发生变化//uniform变量在所有可用的着色阶段之间都是共享的,他必须定义为全局变量。任何类型的变量(包括结构体和数组)//都可以设置为uniform变量,着色器无法写入到uniform变量,也无法改变他的值。//genType radians(genType degrees):从度数转换成弧度//genType normalize(genType x):返回与向量方向一致但长度是1的向量//mat3 outerPRoduct(vec3 c,vec3 r):把第一个参数视作列向量(只有一列的矩阵),把第二个参数视作行向量(只有一行的矩阵)//对矩阵c及r进行线性代数相乘c x r,产生一个行数与c的元素数相同,以及列数与r的元素相同的矩阵。const char* vShader = { "#version 330 core/n" "uniform Uniforms{" " vec3 translation;" " float scale;" " vec4 rotation;" " bool enabled;" "};" "layout(location = 0)in vec2 vPos;" "layout(location = 1)in vec3 vColor;" "out vec4 fColor;" "void main()" "{" " vec3 pos = vec3(vPos,0.0);" " float angle = radians(rotation[0]);" " vec3 axis = normalize(rotation.yzw);" " mat3 I = mat3(1.0);" " mat3 S = mat3(0,-axis.z,axis.y, " " axis.z,0,-axis.x," " -axis.y,axis.x,0);" " mat3 uuT = outerProduct(axis,axis);" " mat3 rot = uuT + cos(angle)*(I - uuT) + sin(angle)*S;" " pos *= scale;" " pos *= rot;" " pos += translation;" " fColor = vec4(vColor,1);" " gl_Position = vec4(vPos,0.0,1);" "}"};const char*fShader = { "#version 330 core/n" "uniform Uniforms{" " vec3 translation;" " float scale;" " vec4 rotation;" " bool enabled;" "};" "in vec4 fColor;" "out vec4 color;" "void main()" "{" " color = fColor;" "}"};size_t TypeSize(GLenum type){ size_t size;#define CASE(Enum,Count,Type)/ case Enum:size = Count * sizeof(Type);break switch (type) { CASE(GL_FLOAT, 1, GLfloat); CASE(GL_FLOAT_VEC2, 2, GLfloat); CASE(GL_FLOAT_VEC3, 3, GLfloat); CASE(GL_FLOAT_VEC4, 4, GLfloat); CASE(GL_INT, 1, GLint); CASE(GL_INT_VEC2, 2, GLint); CASE(GL_INT_VEC3, 3, GLint); CASE(GL_INT_VEC4, 4, GLint); CASE(GL_UNSIGNED_INT, 1, GLuint); CASE(GL_UNSIGNED_INT_VEC2, 2, GLuint); CASE(GL_UNSIGNED_INT_VEC3, 3, GLuint); CASE(GL_UNSIGNED_INT_VEC4, 4, GLuint); CASE(GL_BOOL, 1, GLboolean); CASE(GL_BOOL_VEC2, 2, GLboolean); CASE(GL_BOOL_VEC3, 3, GLboolean); CASE(GL_BOOL_VEC4, 4, GLboolean); CASE(GL_FLOAT_MAT2, 4, GLfloat); CASE(GL_FLOAT_MAT2x3, 6, GLfloat); CASE(GL_FLOAT_MAT2x4, 8, GLfloat); CASE(GL_FLOAT_MAT3, 9, GLfloat); CASE(GL_FLOAT_MAT3x2, 6, GLfloat); CASE(GL_FLOAT_MAT3x4, 12, GLfloat); CASE(GL_FLOAT_MAT4, 16, GLfloat); CASE(GL_FLOAT_MAT4x2, 8, GLfloat); CASE(GL_FLOAT_MAT4x3, 12, GLfloat);#undef CASE default: fprintf(stderr, "Unknow type:0x%x/n", type); exit(EXIT_FAILURE); break; } return size;}enum VAO_IDs{Triangles,NumVAOs};enum Buffer_IDs{ ArrayBuffer0, ArrayBuffer1, NumBuffers };enum Attrib_IDs{vPostion = 0,vColor = 1};GLuint VAOs[NumVAOs];GLuint Buffers[NumBuffers];const GLuint NumVertices = 6;void init(){ GLuint program; glClearColor(1, 0, 0, 1); ShaderInfo shaders[] = { {GL_VERTEX_SHADER,vShader}, {GL_FRAGMENT_SHADER,fShader}, {GL_NONE,NULL} }; program = LoadShaders(shaders); glUseProgram(program); GLuint uboIndex; GLint uboSize; GLuint ubo; GLvoid *buffer; //GLuint glGetUniformBlockIndex(GLuint program,const char * uniformBlockName) //返回program中名称为uniformBlockName的uniform块的索引值。如果uniformBlockName不是一个合法的uniform程序块,那么返回GL_INVALID_INDEX. uboIndex = glGetUniformBlockIndex(program, "Uniforms"); //返回编译器分配的块的大小(根据uniform块的局部设置,编译器可能会自动排除着色器中没有用到的uniform变量)。 glGetActiveUniformBlockiv(program, uboIndex,GL_UNIFORM_BLOCK_DATA_SIZE,&uboSize); buffer = malloc(uboSize); if (buffer == NULL) { fprintf(stderr, "Unable to allocate buffer/n"); exit(EXIT_FAILURE); } else{ enum{Translate,Scale,Rotation,Enabled,NumUniforms}; GLfloat scale = 0.5; GLfloat translation[] = { 0.1, 0.1, 0.0 }; GLfloat rotation[] = { 90, 0.0, 0.0, 1.0 }; GLboolean enabled = GL_TRUE; const char*names[NumUniforms] = { "translation", "scale", "rotation", "enabled" }; GLuint indices[NumUniforms]; GLint size[NumUniforms]; GLint offset[NumUniforms]; GLint type[NumUniforms]; //void glGetUniformIndices(GLuint program,GLsizei uniformCount,const char** uniformNames,GLuint* uniformIndices); //返回所有uniformCount个uniform变量的索引位置,变量的名称通过字符串数组uniformNames来指定,程序返回值保存在数组 //uniformIndices当中。在uniformNames中的每个名称都是以NULL来结尾的,并且uniformNames和uniformIndices的数组元素 //都应该是uniformCount个。如果在uniformNames中给出的某个名称不是当前启用的uniform变量名称,那么uniformIndices中对应 //的位置会记录为GL_INVALID_INDEX. glGetUniformIndices(program, NumUniforms, names, indices); //获得指定索引位置的偏移量和大小 glGetActiveUniformsiv(program, NumUniforms, indices, GL_UNIFORM_OFFSET, offset); glGetActiveUniformsiv(program, NumUniforms, indices, GL_UNIFORM_SIZE, size); glGetActiveUniformsiv(program, NumUniforms, indices,GL_UNIFORM_TYPE,type); memcpy((GLfloat*)buffer + offset[Scale], &scale, size[Scale] * TypeSize(type[Scale])); memcpy((GLfloat*)buffer + offset[Translate], &scale, size[Translate] * TypeSize(type[Translate])); memcpy((GLfloat*)buffer + offset[Rotation], &scale, size[Rotation] * TypeSize(type[Rotation])); memcpy((GLfloat*)buffer + offset[Enabled], &scale, size[Enabled] * TypeSize(type[Enabled])); glGenBuffers(1, &ubo); glBindBuffer(GL_UNIFORM_BUFFER, ubo); glBufferData(GL_UNIFORM_BUFFER, uboSize, buffer, GL_STATIC_DRAW); //void glBindBufferBase(GLenum target,GLuint index,GLuint buffer) //将缓存对象buffer与索引index的命名uniform块关联起来。target可以是GL_UNIFORM_BUFFER或者GL_TRANSFORM_FEEDBACK_BUFFER。 //index是uniform块索引。 glBindBufferBase(GL_UNIFORM_BUFFER, uboIndex, ubo); } glGenVertexArrays(NumVAOs, VAOs); glBindVertexArray(VAOs[Triangles]); GLfloat vertices[NumVertices][2] = { {-0.90,-0.90}, {0.85,-0.90}, {-0.90,0.85}, {0.90,-0.85}, {0.90,0.90}, {-0.85,0.90} }; GLfloat colors[NumVertices][3] = { { 0.0, 1.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 0.0, 1.0, 0.0 }, { 1.0, 1.0, 1.0 }, { 0.0, 0.0, 1.0 }, { 1.0, 1.0, 1.0 }, }; glGenBuffers(NumBuffers, Buffers); glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer0]); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer1]); glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer0]); glVertexAttribPointer(vPostion, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); glEnableVertexAttribArray(vPostion); glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer1]); glVertexAttribPointer(vColor, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0)); glEnableVertexAttribArray(vColor);}void display(void){ glClear(GL_COLOR_BUFFER_BIT); glBindVertexArray(VAOs[Triangles]); glDrawArrays(GL_TRIANGLES, 0, NumVertices); glFlush();}int main(int argc, char** argv){ glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA); glutInitWindowSize(512, 512); glutInitContextVersion(3,3); glutInitContextProfile(GLUT_CORE_PROFILE); glutCreateWindow(argv[0]); glewExperimental = GL_TRUE; if (glewInit()) { cerr << "Unable to initialize GLEW ... exiting" << endl; exit(EXIT_FAILURE); } init(); glutDisplayFunc(display); glutMainLoop();}新闻热点
疑难解答