GLSL 创建自己的着色器
这里讨论如何将类似于上一节的流经着色器编译和链接到OpenGL的程序中去
为了方便编译和修改,着色器程序都写在单独的文本文件中。
1.首先建立一个着色器对象,使用函数glCreateShader()
:
GLuint glCreateShader(GLenum type)
/*type指代着色器类型,GL_VERTEX_SHADER顶点着色器,GL_FRAGMENT_SHADER片段着色器*/
//返回一个唯一的对象标识符
下面代码分别建立了2个着色器对象:
GLuint v,f;
v=glCreateShader(GL_VERTEX_SHADER);
f=glCreateShader(GL_FRAGMENT_SHADER);
这是2个空白着色器,接下来要将它们关联到着色器上,假设2个着色器已经保存在文本文件中,流经顶点着色器保存在passthrough.vert,流经片段着色器保存在passthrough.frag。
首先要将着色器读取到内存中,可以使用CReader或自己写函数。
例:
char *vs=NULL,*fs=NULL;
CReader reader;
vs = reader.textFileRead("passthrough.vert");
fs = reader.textFileRead("passthrough.frag");
2.接着,将读取到内存中的着色器加载到着色器对象中,通过函数glShaderSource()
:
glShaderSource(GLuint unShaderObj,GLsizeit nNoStrings,const GLchar **ppchSource,const GLint nLength);
//该函数将ppchSource中保存的着色器程序放入着色器对象标识符unShaderObj指代的对象中。
//一种常用的参数组合是:将nLength设为NULL,字符串数量nNoStrings设为1,则ppchSources是一个以NULL结尾的字符串
例:
const char *vv=vs;
onst char *ff=fs;
glShaderSource(v,1,&vv,NULL);
glShaderSource(f,1,&ff,NULL);
3.然后对已经加载的着色器进行编译,使用函数glCompileShader()
:
void glCompileShader(GLuint nShaderObj)
例:
glCompileShader(v);
glCompileShader(f);
不在使用着色器时,可以使用glDeleteShader()
删除void glDeleteShader(GLuint nShaderObj)
4.编译结束,该到链接了。在链接着色器对象之前,先要建立程序对象,使用函数:
GLuint glCreateProgram()
5.接下来使用glAttachShader(GLuint nProgramObj,GLuint nShaderObj)
将着色器程序添加到程序对象中去。不在使用某着色器对象时,使用函数void glAttachShader(GLuint nProgramObj,GLuint nShaderObj)
将着色器抽离程序对象。
6.然后使用void glLinkProgram(GLuint nProgramObj)
进行链接。
7.当有多个程序对象时,可以使用void gluseProgram(GLuint nProgramObj)
选择想要使用的程序对象。
例:
GLuint p;
p = glCreateProgram();
glAttachShader(p,v);
glAttachShader(p,f);
glLinkProgram(p);
gluseProgram(p);
8.在程序末尾不在使用某程序时,使用函数void glDeleteProgram(GLuint nProgramObj)
来删除。
注意:编写着色器时:
1.main的返回值必须是void,不能是int;
2.需要下载glew库,并在加入前shader使用glewInit()初始化。
3.严格注意拼写问题!!!
例:
顶点流经着色器vertex.v:
void main()
{vec4 a;a = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;gl_Position.x = a.x*0.4;gl_Position.y = a.y*0.1;
}
片段流经着色器fragment.f:
void main()
{gl_FragColor = vec4(0.4,0.4,0.8,1.0);
}
cpp:
#include <Windows.h>
#include <iostream>
#include<stdlib.h>
#include<gl\glew.h>
//#include <gl\GL.h>
//#include <gl\GLU.h>
#pragma comment(lib,"opengl32.lib")//opengl相关库
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"glew32.lib")
#pragma comment(lib,"glew32s.lib")
/全局句柄
HGLRC hRC;
HDC hDC;
HWND hWnd;
/全局句柄//全局变量
bool flag_depth = true;//是否深度测试
float rx = 0,ry=0;
char *vdata = NULL;
char *fdata = NULL;
GLfloat vec[][3] = {{ -1, 1, -1 }, { 1, 1, -1 }, { 1, 1, 1 }, { -1, 1, -1 }, { 1, 1, 1 }, { -1, 1, 1 },//前{ -1, -1, -1 }, { 1, -1, -1 }, { 1, -1, 1 }, { -1, -1, -1 }, { 1, -1, 1 }, { -1, -1, 1 },//后{ -1, 1, 1 }, { -1, 1, -1 }, { -1, -1, -1 }, { -1, 1, 1 }, { -1, -1, -1 }, { -1, -1, 1 },//左{ 1, 1, 1 }, { 1, 1, -1 }, { 1, -1, -1 }, { 1, 1, 1 }, { 1, -1, -1 }, { 1, -1, 1 },//右{ -1, -1, 1 }, { -1, 1, 1 }, { 1, 1, 1 }, { -1, -1, 1 }, { 1, 1, 1 }, { 1, -1, 1 },//上{ -1, -1, -1 }, { -1, 1, -1 }, { 1, 1, -1 }, { -1, -1, -1 }, { 1, 1, -1 }, { 1, -1, -1 },//下
};
GLfloat col[][3] = {{ 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 0.1, 0.2, 0.3 }, { 0.1, 0.2, 0.3 }, { 0.1, 0.2, 0.3 },//前{ 0.4, 0.4, 0.0 }, { 0.4, 0.4, 0.0 }, { 0.4, 0.4, 0.0 }, { 0.8, 0.4, 0.0 }, { 0.8, 0.4, 0.0 }, { 0.8, 0.4, 0.0 },//后{ 0.8, 0.4, 0.8 }, { 0.8, 0.4, 0.8 }, { 0.8, 0.4, 0.8 }, { 0.0, 0.4, 0.8 }, { 0.0, 0.4, 0.8 }, { 0.0, 0.4, 0.8 },//左{ 0.3, 0.3, 0.3 }, { 0.3, 0.3, 0.3 }, { 0.3, 0.3, 0.3 }, { 0.4, 0.4, 0.4 }, { 0.4, 0.4, 0.4 }, { 0.4, 0.4, 0.4 },//右{ 0.4, 0.0, 0.4 }, { 0.4, 0.0, 0.4 }, { 0.4, 0.0, 0.4 }, { 0.4, 0.0, 0.0 }, { 0.4, 0.0, 0.0 }, { 0.4, 0.0, 0.0 },//上{ 0.0, 0.4, 0.0 }, { 0.0, 0.4, 0.0 }, { 0.0, 0.4, 0.0 }, { 0.0, 0.0, 0.4 }, { 0.0, 0.0, 0.4 }, { 0.0, 0.0, 0.4 },//下
};
void InitGL()//初始化opengl参数
{glClearColor(0.5, 0.5, 0.5, 1);//设置颜色缓存颜色glEnableClientState(GL_VERTEX_ARRAY);
// glEnableClientState(GL_COLOR_ARRAY);glTranslated(0, 0, -1);glVertexPointer(3, GL_FLOAT, 0, vec);
// glColorPointer(3, GL_FLOAT, 0, col);glMatrixMode(GL_PROJECTION); // 选择投影矩阵glLoadIdentity(); // 重置投影矩阵glMatrixMode(GL_MODELVIEW); // 选择模型观察矩阵glLoadIdentity(); // 重置模型观察矩阵glScalef(0.5,0.5,0.5); //缩放0.5倍}
char* ReadFile(char *filename)
{FILE *file = NULL;fopen_s(&file, filename, "rt");if (file == NULL){return NULL;}fseek(file, 0, SEEK_END);long count = ftell(file);rewind(file);char *fileData = NULL;if (count > 0){fileData = new char[count+1];fread(fileData, sizeof(char), count, file);fileData[count] = '\0';}return fileData;
}
void setShader()
{glewInit();//添加此句GLuint v, f;v = glCreateShader(GL_VERTEX_SHADER);f = glCreateShader(GL_FRAGMENT_SHADER);vdata = ReadFile("vertex.v");fdata = ReadFile("fragment.f");char *vv = vdata;char *ff = fdata;glShaderSource(v, 1, &vv, NULL);glShaderSource(f, 1, &ff, NULL);glCompileShader(v);glCompileShader(f);GLuint p = glCreateProgram();glAttachShader(p, v);glAttachShader(p, f);glLinkProgram(p);glUseProgram(p);}
void DrawGLScene()
{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // 每次刷新屏幕颜色缓存if (flag_depth) glEnable(GL_DEPTH_TEST);else glDisable(GL_DEPTH_TEST);glRotated(rx, 1, 0, 0);glRotated(ry, 0, 1, 0);glDrawArrays(GL_TRIANGLES, 0, 36);}
LRESULT CALLBACK WndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)// 消息处理回调函数
{switch (uMsg) // Check For Windows Messages{case WM_ACTIVATE: // Watch For Window Activate Message{return 0; // Return To The Message Loop}case WM_SYSCOMMAND: // Intercept System Commands{switch (wParam) // Check System Calls{case SC_SCREENSAVE: // Screensaver Trying To Start?case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?return 0; // Prevent From Happening}break; // Exit}case WM_CLOSE: // Did We Receive A Close Message?{PostQuitMessage(0); // Send A Quit Messagereturn 0; // Jump Back}case WM_KEYDOWN: // 按键按下 由wParam决定{switch (wParam){case 'D':flag_depth = !flag_depth;break;case VK_UP:rx += 0.001;break;case VK_DOWN:rx -= 0.001;break;case VK_LEFT:ry += 0.001;break;case VK_RIGHT:ry -= 0.001;break;}return 0; // Jump Back}case WM_KEYUP: // 按键松开{return 0; // Jump Back}case WM_SIZE: // Resize The OpenGL Window{glViewport(0, 0, LOWORD(lParam), HIWORD(lParam));//改变GL窗口大小return 0; // Jump Back}case WM_PAINT:{DrawGLScene(); // Draw The SceneSwapBuffers(hDC); // Swap Buffers (Double Buffering)return 0; // Jump Back}}// Pass All Unhandled Messages To DefWindowProcreturn DefWindowProc(hwnd, uMsg, wParam, lParam);//默认消息回调处理函数
}
void KillGLWindow()
{if (hRC) // 删除着色描述表{if (!wglMakeCurrent(NULL, NULL)) // Are We Able To Release The DC And RC Contexts?{MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);}if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?{MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);}hRC = NULL; // Set RC To NULL}if (hDC && !ReleaseDC(hWnd, hDC)) // 释放DC{MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);hDC = NULL; // Set DC To NULL}if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?{MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);hWnd = NULL; // Set hWnd To NULL}}
int WINAPI WinMain(HINSTANCE h,HINSTANCE,LPSTR lpCmdLine,int nCmdShow)
{WNDCLASS wc;wc.hInstance = h;wc.hbrBackground = NULL;wc.hCursor = LoadCursor(NULL, IDC_ARROW);wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);wc.lpszMenuName = NULL;wc.lpszClassName = "OpenGL";wc.cbClsExtra = 0; // No Extra Window Datawc.cbWndExtra = 0;wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.wc.lpfnWndProc = (WNDPROC)WndProc;RegisterClass(&wc);hWnd = CreateWindow("OpenGL", "test", WS_OVERLAPPEDWINDOW | WS_SYSMENU | WS_BORDER | WS_MAXIMIZEBOX, 0, 0, 300, 300, NULL, NULL, h, NULL);//opengl设定hDC = GetDC(hWnd);static PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be{sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor1, // Version NumberPFD_DRAW_TO_WINDOW | // Format Must Support WindowPFD_SUPPORT_OPENGL | // Format Must Support OpenGLPFD_DOUBLEBUFFER, // Must Support Double BufferingPFD_TYPE_RGBA, // Request An RGBA Format24, // Select Our Color Depth0, 0, 0, 0, 0, 0, // Color Bits Ignored0, // No Alpha Buffer0, // Shift Bit Ignored0, // No Accumulation Buffer0, 0, 0, 0, // Accumulation Bits Ignored16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer0, // No Auxiliary BufferPFD_MAIN_PLANE, // Main Drawing Layer0, // Reserved0, 0, 0 // Layer Masks Ignored};int PixelFormat;if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) // 按照给定像素格式规范匹配与设备上下文合适的像素格式{KillGLWindow(); // 重置显示区MessageBox(NULL, "不能设置像素格式", "错误", MB_OK | MB_ICONEXCLAMATION);return FALSE; // 返回 FALSE}if (!SetPixelFormat(hDC, PixelFormat, &pfd)) // 设置像素格式{KillGLWindow(); // 重置显示区MessageBox(NULL, "不能设置像素格式", "错误", MB_OK | MB_ICONEXCLAMATION);return FALSE; // 返回 FALSE}if (!(hRC = wglCreateContext(hDC))) // 设置合适设备的OpenGL渲染上下文{KillGLWindow(); // 重置显示区MessageBox(NULL, "不能创建OpenGL渲染描述表", "错误", MB_OK | MB_ICONEXCLAMATION);return FALSE; // 返回 FALSE}if (!wglMakeCurrent(hDC, hRC)) // 尝试激活着色描述表{KillGLWindow(); // 重置显示区MessageBox(NULL, "不能激活当前的OpenGL渲然描述表", "错误", MB_OK | MB_ICONEXCLAMATION);return FALSE; // 返回 FALSE}//opengl着色表设定结束ShowWindow(hWnd, SW_SHOW);InitGL();//opengl相关初始化setShader();//消息处理bool done = false;MSG msg;while (!done) // Loop That Runs While done=FALSE{if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // 如果有消息就处理消息{if (msg.message == WM_QUIT) // Have We Received A Quit Message?{done = TRUE; // If So done=TRUE}else // If Not, Deal With Window Messages{TranslateMessage(&msg); // Translate The MessageDispatchMessage(&msg); // Dispatch The Message}}else // 没消息就处理界面{// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene() }}return TRUE;
}
GLSL 创建自己的着色器相关推荐
- OpenGl学习笔记二:创建自己的着色器
1. GLSL 着色器是使用一种叫GLSL的类C语言写成的.GLSL是为图形计算量身定制的,它包含一些针对向量和矩阵操作的有用特性. 从基本意义上来说,着色器只是一种把输入转化为输出的程序.着色器也是 ...
- Learn OpenGL(七)——OpenGL中使用着色器的基本步骤及GLSL渲染简单示例
OpenGL着色语言(OpenGL Shading Language,GLSL)是用来在OpenGL中着色编程的语言,是一种具有C/C++风格的高级过程语言,同样也以main函数开始,只不过执行过程是 ...
- “着色器”是什么意思? 如何使用HTML5和WebGL创建它们
本文是Microsoft的Web开发技术系列的一部分. 感谢您支持使SitePoint成为可能的合作伙伴. 您可能已经注意到,去年我们第一次谈论了babylon.js ,最近发布了带有3D声音定位(使 ...
- 第四章:缓冲区、着色器、GLSL
原文链接: http://www.rastertek.com/gl40tut04.html Tutorial 4: Buffers, Shaders, and GLSL 第四章:缓冲区.着色器.GLS ...
- unity Shader Lab(cg hlsl glsl)着色器入门教程 以及 vs2019 支持unity shader语法(更新中2019.9.5)
前言: 如果你对cg glsl hlsl 顶点着色器 片段着色器 表面着色器 固定渲染管线 等等有所疑惑,或是想学会unity的渲染,看这一篇就足够了.另外我博客的shader分类中还有很多shade ...
- webgl 着色器_“着色器”是什么意思? 如何使用HTML5和WebGL创建它们
webgl 着色器 本文是Microsoft的Web开发技术系列的一部分. 感谢您支持使SitePoint成为可能的合作伙伴. 您可能已经注意到,去年我们第一次谈论了babylon.js ,最近我们发 ...
- openglshader实现虚拟场景_opengl – 如何使用GLSL着色器将径向模糊应用于整个场景?...
我在GLSL中有一个径向模糊着色器,它采用纹理,对其进行径向模糊,并将结果呈现给屏幕.这个工作很好,到目前为止. 问题在于,它将径向模糊应用于场景中的第一个纹理.但是我实际上想做的就是将这个模糊应用于 ...
- [Shader] Shader Cookbook 创建你的第一个着色器[1]
本章将涵盖一些在今天的游戏开发阴影管道中发现的更常见的扩散技术.让我们想象一个立方体,它被均匀地涂成白色,在一个有定向光的3D环境中.即使在每张脸上使用的颜色是相同的,它们也会有不同的白色深浅,这 ...
- 从头开始学习Unity着色器
MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语+中英文字幕(根据原英文字幕机译更准确)|时长:56节课(4h 26m) |大小解压后:2.89 GB ...
- c语言opengles程序,OpenGL ES _ 着色器_程序
演示图 你不知道这个东西,请不要看了,请看我的其他文章先了解一下O! 学习目标 掌握着色器程序的执行过程 简单的例子 `` uniform float t; // 时间 uniform mat4 gl ...
最新文章
- 重试次数配置_TestNG实践——2.用例失败重试
- Boost:bind绑定的==,!=,<,<=,>,> =运算符的测试程序
- python快速学_python快速学习4
- CentOS6.8升级gcc到4.8.5总结
- python变量命名可以有特殊符号吗,和孩子一起学习python之变量命名规则
- 下周开幕!给深圳的嵌入式和电子工程师准备的嘉年华来了
- Redis Key过期及清除策略
- 创建完美SDK的10个技巧
- 什么都懂, 为什么没有业绩?
- Unity ToLua 中Update的调用流程
- ssh连接Linux很慢,且ssh传输文件很慢的解决方案
- 为Android GridView 设置行背景
- java环境安装包_超详细的EFK安装部署教程--环境准备篇
- WPF编程基础入门 ——— 第三章 布局(四)布局面板StackPanel
- echarts自动排序_百度echarts 排序问题
- 《网络科学导论》——博弈模型笔记
- Java8新特性之双冒号(::)
- 【光学设计基础】--01像差理论基础
- unity lookat导致物体颠倒怎么解决_在Unity 2D中如何用一行代码实现LookAt的效果,以及向量归一化小总结...
- HTML5 canvas 拖尾效果(或尾巴 或方向标 或留痕。。。)
热门文章
- 找出01二维矩阵中只包含 1 的最大正方形,并输出其面积_java
- 小米笔记本pro lol测试软件,小米笔记本ProGTX版评测 到底好不好用
- ACDSee Photo Manager 15.0.169 crack by XenoCoder
- Pandas处理和转置excel数据
- Excel 转置分组时如何保留没有对应数据的空组
- linux命令批量修改文件名称
- android仿微信的开门效果
- 打印机怎么设置扫描到计算机,打印扫描一体机怎么扫描_怎样用打印机扫描文件到电脑-win7之家...
- 扫描全能王添加头像的方法
- Node.js meitulu图片批量下载爬虫 1.05版(Final最终版)