OpenGL|OpenGL--shader入门
- 理论基础
着色器:opengl渲染管线分为固定管线和可编程管线,3.1版本后固定管线已经废除了。可编程管线主要是包括顶点着色器和片段着色器,而我们所讲的shader其实就是说我们可以自己控制这两个阶段的操作。本质其实和固定管线一样,还是走那套流程,只是现在更灵活些而已。
下面是着色器编程的步骤示意图:
文章图片
- 实例代码
#include "GLTools.h"
#include "GLShaderManager.h"#ifdef __APPLE__
#include
#else
#define FREEGLUT_STATIC
#include
#endifGLuint v, f, f2,p;
GLint loc;
//文件读取(将本地shader文件读取为字符串形式加载)
char *textFileRead(char *fn)
{
FILE *fp;
char *content = NULL;
int count=0;
if (fn != NULL)
{
fp = fopen(fn,"rt");
if (fp != NULL)
{
fseek(fp, 0, SEEK_END);
count = ftell(fp);
rewind(fp);
if (count > 0)
{
content = (char *)malloc(sizeof(char) * (count+1));
count = fread(content,sizeof(char),count,fp);
content[count] = '\0';
}
fclose(fp);
}
}
return content;
}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);
}float time = 0;
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor4f(1.0, 0.0, 0.0, 1.0);
//初始化了gl_Color值,可给着色器使用glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glUniform1f(loc, time);
//给uniform属性loc所指地址赋值
time+=0.01;
glutSolidTeapot(1);
//绘制茶壶glutSwapBuffers();
}//着色器:自己处理渲染管线中的顶点着色器和片段着色器阶段
void setShaders()
{
char *vs = NULL, *fs = NULL, *fs2 = NULL;
/*第一阶段*/
//创建着色器对象(类似C中的函数,可以复用)
v = glCreateShader(GL_VERTEX_SHADER);
//顶点着色器
f = glCreateShader(GL_FRAGMENT_SHADER);
//片段着色器
f2 = glCreateShader(GL_FRAGMENT_SHADER);
vs = textFileRead("/Users/app05/Desktop/opengl/opengl/minimal.vert");
fs = textFileRead("/Users/app05/Desktop/opengl/opengl/minimal.frag");
const char *vv = vs;
const char *ff = fs;
//将着色器代码添加到创建的着色器容器中
glShaderSource(v, 1, &vv, NULL);
glShaderSource(f, 1, &ff, NULL);
free(vs);
free(fs);
//编译着色器源代码
glCompileShader(v);
glCompileShader(f);
/*第二阶段*/
p = glCreateProgram();
//创建着色器程序
glAttachShader(p, v);
//将着色器对象关联到这个着色器程序
glAttachShader(p, f);
glLinkProgram(p);
//链接着色器程序glUseProgram(p);
//使用着色器//得到着色器程序中unifrom属性的time变量地址,以便外面修改它
loc = glGetUniformLocation(p,"time");
}int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("OpenGL Shader 入门");
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
glEnable(GL_DEPTH_TEST);
glClearColor(1.0,1.0,1.0,1.0);
//glEnable(GL_CULL_FACE);
glewInit();
setShaders();
glutMainLoop();
return 0;
}
//顶点着色器程序(minimal.vert)
uniform float time;
//uniform属性的变量值可以由opengl程序传进来void main()
{
//顶点颜色
gl_FrontColor = gl_Color;
//模型矩阵变换,将3D坐标投影到2D屏幕坐标
//gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
//gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
//gl_Position = ftransform();
//实例:顶点z值正旋变化
vec4 v = vec4(gl_Vertex);
v.z = sin(5.0 * v.x + time) * 0.5;
gl_Position = gl_ModelViewProjectionMatrix * v;
}
//片段着色器程序(minimal.frag)
void main()
{
/*gl_FragColor:是设置片段的颜色,gl_Color:是外部glColor()默认初始化的uniform值*/
gl_FragColor = gl_Color;
}
文章图片
【OpenGL|OpenGL--shader入门】
文章图片
推荐阅读
- typeScript入门基础介绍
- Android|Android sqlite3数据库入门系列
- Android下的IO库-Okio源码解析(一)|Android下的IO库-Okio源码解析(一) 入门
- 深度学习-入门
- 第三章|第三章 进校园重拾旧梦 登讲台初为人师第一节 接乱班面临考验 ,遇高师指点入门
- iOS开发技术之美—iOS入门技术的基础学习
- OpenCV|OpenCV-Python实战(18)——深度学习简介与入门示例
- 2.关于OpenGL|2.关于OpenGL 坐标系以及渲染流程
- 【入门】Python网络爬虫与信息提取1
- 垂直农场101-室内农业入门知识