OpenGL GLSL
来源:互联网 发布:上海知恩服饰有限公司 编辑:程序博客网 时间:2024/05/01 16:11
GLSL是OpenGL的着色语言, 我们之前的例子,都是用的着色器管理类GLShaderManager中的函数UseStockShader来使用着色器的,该函数完成的东西就是对我们的顶点数据进一步的加工,比如设置顶点颜色,设置顶点光照的强度,设置顶点纹理等。
假如说我们对UseStockShader函数一些默认的效果不满意,比如我们要让模型的一部分比另一部分更亮,也就是光线照到的地方,比没有照到的地方要亮,这个时候就要写自己的着色器。
如下图:
这也是我们这一节要实现的例子,模型的左上角比较亮。
着色器分为顶点着色器 ,几何着色器,片段着色器,本节只介绍顶点着色器和片段着色器
顶点着色器记录的是顶点的属性和一些对顶点的操作,顶点着色器的文件后缀为,vp
片段着色器记录的是片段的属性和一些对片段的操作,片段着色器的文件后缀是.fp
片段的意思就是组成模型的最小单元,比如一个三角形就是一个片段
顶点着色器在处理顶点后会将处理的结果传给片段着色器
着色器的入口函数同样是main函数
下面先写一个我们的顶点着色器,写完后我们在说怎么用它
创建一个记事本名字叫做DiffuseLight.txt,然后把后缀名改成.vp,最后是DiffuseLight.vp
在GLSL语言中,我们可以用vec3声明一个三维向量,vec4声明一个4维向量,用mat4声明一个4*4的矩阵,用mat3声明一个3*3的矩阵
我们在DiffuseLight.vp先来声明一下我们的全局变量
//指定OpenGL的最低版本为1.3#version 130//关键字in表示是要从外界输入的变量in vec4 vVertex;in vec3 vNormal;//关键字uniform 表示统一值的意思uniform vec4diffuseColor;//漫反射光的颜色值uniform vec3vLightPosition; //光源的位置uniform mat4mvpMatrix; //模型视图投影矩阵uniform mat4mvMatrix; //视图矩阵uniform mat3normalMatrix; //模型视图的法线矩阵//关键字out表示的是输出的值,也就是传给片段着色器的值,smooth表示颜色值vVaryingColor采用平滑插值的方式smooth out vec4 vVaryingColor;
其中#version用来指导OpenGL的版本,#version 130 表示该着色器要求OpenGL的版本最低是1.3
关键字in表示是要从外界输入的变量,我们要从外界输入模型的顶点vVertex,模型顶点的法线vNormal
关键字uniform 表示统一值的意思,也就是该图元都使用的一些相同的属性值,如果说图元是三角形,那么就表示三角形的三个顶点使用的都是统一值定义的属性值
统一值可以从外界赋值
我们可以用函数 glGetUniformLocation GLEW_GET_FUN(__glewGetUniformLocation) 来从外界获取这个统一值的字段
比如:
GLint locColor = glGetUniformLocation(diffuseLightShader, "diffuseColor");
我们可以用函数glUniform4fv 来设置一个四维向量的字段值
比如:
GLfloat vDiffuseColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };glUniform4fv(locColor, 1, vDiffuseColor);
设置四维矩阵的方法是glUniformMatrix4fv
设置三维矩阵的方法是glUniformMatrix3fv
最后的smooth out vec4 vVaryingColor,表示我们会把颜色值vVaryingColor传到片段着色器里
下面来看我们的main函数
void main(void) { // 把顶点的法线转换到模型视图变换矩阵中vec3 vEyeNormal = normalMatrix * vNormal;// 把顶点转换到照相机坐标系vec4 vPosition4 = mvMatrix * vVertex;//去除顶点的缩放,还原为原状态vec3 vPosition3 = vPosition4.xyz / vPosition4.w;// 得到顶点到光源的方向vec3 vLightDir = normalize(vLightPosition - vPosition3);//函数dot表示 用顶点到光源的方向乘以顶点的法线,得到夹角的余弦值//函数max表示将得到的余弦值和0作比较,取最大的float diff = max(0.0, dot(vEyeNormal, vLightDir));// 设置顶点的颜色,用上一步得到的diff乘以原来顶点的颜色,并保持alphp不变vVaryingColor.rgb = diff * diffuseColor.rgb;vVaryingColor.a = diffuseColor.a;// 把顶点的投影到模型视图矩阵中gl_Position = mvpMatrix * vVertex; }
首先一定要记得,我们自己写顶点着色器程序,那么一些顶点的位置,光照强度,颜色,矩阵空间的变换都是有我们自己控制的
下面来写我们的片段着色器程序,建一个名为DiffuseLight.fp的文件,注意后缀为.fp
下面是DiffuseLight.fp中的内容
#version 130//从顶点着色器接受的值smooth in vec4 vVaryingColor;out vec4 vFragColor;void main(void) { vFragColor = vVaryingColor; }
片段着色器比较简单 首先我们要接受顶点着色器传过来的颜色值vVaryingColor,并且名义一定要一样,然后我们声明一个传入光栅化阶段的颜色值vFragColor,vFragColor只是简单的和vVaryingColor相等,我们并没有做其他的操作
下面来看一下我们是怎么来用这两个文件的
我们创建一个新的OpenGL工程,添加一个.cpp源文件
首先来看一下我们需要包含的头文件和全局变量部分
#include <GLTools.h>#include <GLMatrixStack.h>#include <GLFrame.h>#include <GLFrustum.h>#include <GLGeometryTransform.h>#include <StopWatch.h>#include <math.h>#define FREEGLUT_STATIC#include <GL/glut.h>GLFrame viewFrame;GLFrustum viewFrustum;GLTriangleBatch sphereBatch;GLMatrixStack modelViewMatrix;GLMatrixStack projectionMatrix;GLGeometryTransform transformPipeline;GLShaderManager shaderManager;GLuintdiffuseLightShader;GLintdiffuseColor;GLintvLightPosition;GLintmvpMatrix;GLintmvMatrix;GLintnormalMatrix;
我们可以看到最后五个参数和我们顶点着色器中的创建的5个统一值uniform参数是一样的
下面是主函数main,和之前的代码一样
int main(int argc, char* argv[]) {//设置工作路径gltSetWorkingDirectory(argv[0]);//初始化glutglutInit(&argc, argv);//申请一个带有双缓冲区,颜色缓冲区的窗口glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);//窗口大小glutInitWindowSize(800, 600);//窗口名字glutCreateWindow("GLSL");//窗口大小改变时的回调函数glutReshapeFunc(ChangeSize);//键盘按键响应函数glutSpecialFunc(SpecialKeys);//渲染的回调函数glutDisplayFunc(RenderScene);GLenum err = glewInit();if (GLEW_OK != err) {fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));return 1;}//初始化函数SetupRC();//主函数循环glutMainLoop();//循环结束后释放内存ShutdownRC();return 0; }
然后是窗口改变大小时的回调函数ChangeSize
void ChangeSize(int nWidth, int nHeight) {//设置视口大小glViewport(0, 0, nWidth, nHeight);//将视图变换矩阵 和 模型 变换矩阵统一管理起来transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);//设置视口变换矩阵viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f);//设置模型变换矩阵projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());}
下面是初始化函数SetupRC
我们可以用方法GLuint LoadShaderPairWithAttributes(const char *szVertexProgFileName, const char *szFragmentProgFileName, ...);
来加载我们自己写的着色器文件
void SetupRC(void){glClearColor(0.3f, 0.3f, 0.3f, 1.0f );glEnable(GL_DEPTH_TEST);glEnable(GL_CULL_FACE);shaderManager.InitializeStockShaders();viewFrame.MoveForward(4.0f);gltMakeSphere(sphereBatch, 1.0f, 26, 13);//加载着色器,并设置需要传入着色器中的属性字段名diffuseLightShader = shaderManager.LoadShaderPairWithAttributes("DiffuseLight.vp", "DiffuseLight.fp", 2, GLT_ATTRIBUTE_VERTEX, "vVertex",GLT_ATTRIBUTE_NORMAL, "vNormal");//得到顶点着色器中漫反射光颜色diffuseColor的位置引用diffuseColor = glGetUniformLocation(diffuseLightShader, "diffuseColor");//得到顶点着色器中光源vLightPosition位置的位置引用vLightPosition = glGetUniformLocation(diffuseLightShader, "vLightPosition");//的到顶点着色器中模型视图矩阵mvpMatrix的位置引用mvpMatrix = glGetUniformLocation(diffuseLightShader, "mvpMatrix");//得到顶点着色器中视图变换矩阵mvMatrix的位置引用mvMatrix = glGetUniformLocation(diffuseLightShader, "mvMatrix");//得到顶点着色器中模型视图矩阵normalMatrix的位置引用normalMatrix = glGetUniformLocation(diffuseLightShader, "normalMatrix");}
下面是渲染函数RenderScene
我们可以使用函数glUseProgram 来使用着色器,其中参数是函数LoadShaderPairWithAttributes的返回值
void RenderScene(void){static CStopWatch rotTimer;glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);modelViewMatrix.PushMatrix(viewFrame);modelViewMatrix.Rotate(rotTimer.GetElapsedSeconds() * 10.0f, 0.0f, 1.0f, 0.0f);GLfloat vEyeLight[] = { -100.0f, 100.0f, 100.0f };GLfloat vDiffuseColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };//使用着色器glUseProgram(diffuseLightShader);//设置顶点着色器中的漫反射光diffuseColor的颜色值glUniform4fv(diffuseColor, 1, vDiffuseColor);//设置顶点着色器中的光源位置vLightPosition的值glUniform3fv(vLightPosition, 1, vEyeLight);//设置顶点着色器中的模型视图矩阵mvpMatrix值glUniformMatrix4fv(mvpMatrix, 1, GL_FALSE, transformPipeline.GetModelViewProjectionMatrix());//设置顶点着色器中的视图面环矩阵值mvMatrixglUniformMatrix4fv(mvMatrix, 1, GL_FALSE, transformPipeline.GetModelViewMatrix());//设置顶点着色器中的模型视图矩阵法线矩阵normalMatrix值glUniformMatrix3fv(normalMatrix, 1, GL_FALSE, transformPipeline.GetNormalMatrix());//绘制模型sphereBatch.Draw();modelViewMatrix.PopMatrix();glutSwapBuffers();glutPostRedisplay();}
- OpenGL GLSL
- opengl glsl 深度计算
- OpenGL GLSL uniform variable
- OpenGL GLSL Blocks
- OpenGL GLSL Blocks example
- OpenGL GLSL Shader Subroutines
- OpenGL 与 GLSL 版本
- OpenGL 与 GLSL 版本
- OpenGL GLSL访问纹理
- OpenGL GLSL 丢弃片段
- OpenGL着色语言GLSL
- OpenGL 例子 glsl
- [OpenGL] 你好,GLSL
- OpenGL着色语言GLSL
- opengl编程glsl-纹理
- GLSL教程 OpenGL Setup for GLSL 综述
- GLSL教程 OpenGL Setup for GLSL 清理
- GLSL 在OpenGL中使用GLSL
- 面试经典问题
- 搭建聊天的界面、输入图片和文本
- java反射机制之基础
- 我和敏捷开发的故事--敏捷角色PO
- 利用json转变Python格式
- OpenGL GLSL
- 删数问题-注意贪心策略-不严格
- [Error]No enclosing instance of type XX is accessible. Must qualify the allocation with an e
- 暑假-二分图-D - Uncle Tom's Inherited Land
- 问题
- OC中如何进行多文件开发?
- iOS——创建Xcode 的Hello World
- 做葡萄酒全过程
- Linux/ubuntu 截图工具的使用