GLSL 创建自己的着色器
来源:互联网 发布:编程c语言入门 编辑:程序博客网 时间:2024/06/07 21:11
这里讨论如何将类似于上一节的流经着色器编译和链接到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 Message return 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 Scene SwapBuffers(hDC); // Swap Buffers (Double Buffering) return 0; // Jump Back } } // Pass All Unhandled Messages To DefWindowProc return 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 Data wc.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 Descriptor 1, // Version Number PFD_DRAW_TO_WINDOW | // Format Must Support Window PFD_SUPPORT_OPENGL | // Format Must Support OpenGL PFD_DOUBLEBUFFER, // Must Support Double Buffering PFD_TYPE_RGBA, // Request An RGBA Format 24, // Select Our Color Depth 0, 0, 0, 0, 0, 0, // Color Bits Ignored 0, // No Alpha Buffer 0, // Shift Bit Ignored 0, // No Accumulation Buffer 0, 0, 0, 0, // Accumulation Bits Ignored 16, // 16Bit Z-Buffer (Depth Buffer) 0, // No Stencil Buffer 0, // No Auxiliary Buffer PFD_MAIN_PLANE, // Main Drawing Layer 0, // Reserved 0, 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 Message DispatchMessage(&msg); // Dispatch The Message } } else // 没消息就处理界面 { // Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene() } } return TRUE;}
- GLSL 创建自己的着色器
- GLSL教程 OpenGL Setup for GLSL 创建着色器
- GLSL教程 OpenGL Setup for GLSL 创建着色器程序
- 创建自己的着色器程序
- OpenGL 着色器语言GLSL的数据类型
- 着色器glsl
- glsl 细分着色器
- GLSL(着色器语言)
- opengl编程glsl-着色器
- GLSL-使用Uniform Block实现着色器的数据共享
- GLSL橙宝书中简单的着色器代码
- 基于Qt和GLSL的着色器例子
- 场景中多个点光源的着色器GLSL代码
- 渲染世界的OPENGL<9>GLSL编程-单位着色器
- 06 WebGL 着色器编程语言GLSL ES的数组
- 10 WebGL 着色器编程语言GLSL ES的函数
- GLSL-使用Subroutines选择着色器功能
- GLSL opengl着色器参数传递Shader
- Linux下Hadoop Eclipse插件编译安装
- delphi xe2下载地址
- ubuntukylin 14.04 下安装matlab2009
- JNative的初步使用
- 硬件设计之继电器控制
- GLSL 创建自己的着色器
- hadoop程序问题:java.lang.IllegalArgumentException: Wrong FS: hdfs:/ expected file:///
- jsp页面中的EL表达式不被解析的问题
- 今天访问数据库的时候出现提示信息
- php-fpm
- JAVA调用动态链接库DLL之JNative学习
- Unity基于ZXing.Net实现二维码的制作
- uva11538(数论)
- 博弈论 PN点