#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.1415926
GLuint vaoHandle;
GLuint programHandle;
float angle = 30.0f * PI/180.0f;//转换为弧度制
void InitUniformBlockBuffer();
//we create and populate the vertex buffer objects for each attribute
float 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
};//上面的六个点刚好形成一个正方形
//三角形三个顶点,每个顶点的RGB
float colorData[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
//正方形四个顶点,每个顶点的RGB
float 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 430
layout (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 430
in 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));
}
结果: