實現程序:
#include "stdafx.h"#include<iostream>using namespace std;#include "vgl.h"#include "LoadShaders.h"http://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"); //返回編譯器分配的塊的大?。ǜ鶕niform塊的局部設置,編譯器可能會自動排除著色器中沒有用到的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();}新聞熱點
疑難解答