opengl shader 学习 随笔四

时间:2022-03-02 19:34:12
一个典型的shader程序,看完这个基本shader的流程就没有问题了。
const char *vShader = {   //Vertex shader
"#version 330 core\n"
"uniform Uniforms{"
"vec3 translation;"
"float scale;"
"vec4 rotation;"
"bool enabled;"
"};"
"in vec2 vPos;"
"in vec3 vColor;"
"out vec4 fColor;"
"void main()"
"{"
"vec3 pos = vec3(vPos,0.0);"
"float angle = radians(rotation[0]);"
"vec3 axis = normalize(rotaion.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(scale,scale,scale,1);"
"gl_Position = vec4(pos,1);"
"}"
};

const char* fShader{ //Fragment shader
"#version 330 core\n"
"uniform Uniforms{"
"vec3 translation;"
"float scale;"
"vec4 rotation;"
"bool enabled;"
"};"
"int vec4 fColor;"
"out vec4 color;"
"void main()"
"{"
"color = fColor;"
"}"
};

size_t TypeSize(GLenum type) //定义shader中的类型转换函数
{
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, "Unknown type: 0x%x\n", type);
exit(EXIT_FAILURE);
break;
}
return size;
}

void init()//主程序
{
GLuint program; //定义progarm和shader
glClearColor(1,0,0,1);
ShaderInfo shaders[]={
{GL_VERTEX_SHADER,vShader},
{GL_FRAGMENT_SHADER,fShader},
{GL_NONE,NULL}
};
program = LoadShaders(shaders); //加载shader到program中,并且使用program;
glUseProgram(program);

//初始化shader中的uniform块中数据
GLuint uboIndex;
GLint uboSize;
GLuint ubo;
GLvoid *buffer;

uboIndex = glGetUniformBlockIndex(program,"Uniforms");

glGetUniformBlockiv(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
{
enmu {Translation,Scale,Rotation,Enabled,NumUniforms};

//初始化uniform中的值
GLfloat translation[]={0.1,0.1,0.0};
GLfloat scale = 0.5;
GLfloat rotation[]={90,0.0,0.0,0.1};
GLboolean enabled = GL_TRUE;

//Uniforms 中的字符队列
const char* names[NumUniforms]={
"translation","scale","rotation","enabled"
};
//查询相应的变量的属性
GLuint indices[NumUniforms];
GLint size[NumUniforms];
GLint offset[NumUniforms];
GLint type[NumUniforms];

glGetUniformsIndices(program,NumUniforms,names,indices);
glGetActiveUniformsiv(program,NumUniforms,indices,GL_UNIFORM_OFFSET,offset);
glGetActiveUniformsiv(program,NumUniforms,indices,GL_UNIFORM_SIZE,size);
glGetAcitveUniformsiv(program,NumUniforms,indices,GL_UNIFORM_TYPE,type);

//将uniform的值复制进buffer中
memcpy(buffer+offset[Scale],&scale,size[Scale]*TypeSize(type[Scale]));
memcpy(buffer+offset[Translation],&translation,size[Translation]*TypeSize(type[Translation]));
memcpy(buffer+offset[Rotation],&rotation,size[Rotaion]*TypeSize(type[Rotation]));
memcpy(buffer+offset[Enabled],&enabled,size[Enabled]*TypeSize(type[Enabled]));
//创建uniform buffer对象,将其与shader连接起来

glGenBuffers(1,*ubo);
glBindBuffer(GL_UNIFORM_BUFFER,ubo);
glBufferData(GL_UNIFORM_BUFFER,ubosize,buffer,GL_STATIC_RAW);
glBindBufferBase(GL_UNIFORM_BUFFER,uboIndex,ubo);

}
}

至此整个程序OK了,第一个shader就可以用了。