GLSL着色器实现高斯滤波代码
来源:互联网 发布:js table tbody 编辑:程序博客网 时间:2024/06/06 19:46
刚开始学习GLSL的时候,感觉非常痛苦,资料非常少是一个原因,更重要的原因就是没有现成的可运行的代码可以,后来在ARC公司实习花了一个月吧,终于对GLSL作为加速计算的方面的知识有了一定的了解。感谢ARC,感谢我的师傅兼师兄孙XX!
请不要将将此代码用于商业用途,如转载,请注明出处:http://blog.csdn.net/gningh/article/details/9615631
我所做的工作并不是用GLSL实现各种绚丽的图形渲染,而是用它做图像处理和加速运算。
这里有一些小的注意事项,
1.我们处理图像的时候一般是把图像载入纹理缓冲,当做纹理来处理,这样可以加快速度。
2.纹理坐标默认的是归一化的坐标形式,我们这里用的是原始的图像坐标,这样可以更加容易写代码。可以了解一下texture2DRect与textu2D的区别
3.代码中使用了一个LoadBMP函数,这个函数在<LoadBMP.h>中定义的。这个函数是公司的,所以我不能侵权把它贴出来,大家可以自己从网上搜索读取BMP的函数,一搜一大片,这个函数主要的目的就是取得BMP图像的数据的指针,而且这个函数功能有点弱,只能读取24位的BMP。
4.高斯模板我用的是
下面就是代码了:
// //#include "stdafx.h"#include <windows.h>#include <stdio.h>#include <stdlib.h>#include <GL/glew.h>#include <GL/glut.h>#include "LoadBMP.h"//纹理的编号static GLuint texture; #define printOpenGLError() printOglError(__FILE__, __LINE__)//纹理图像的高和宽const GLint imgHeight = 512, imgWidth = 512;//顶点着色器const char *vShader = {"#version 110 \n ""void main()""{""gl_TexCoord[0] = gl_MultiTexCoord0;" "gl_Position = ftransform();""}"};/***************片元着色器代码**************************注意代码中的pos变量代表的是实际的坐标,因为读入bmp图像的**数据后,数据是从下往上存放的,这里要将坐标纠正一下。加入\n**是为了在编译着色器代码时可以准确找到出错的行数,否则**显示的都是一行**********************************************************/const char *fShader = {"#version 100 \n ""#extension GL_ARB_texture_rectangle : enable \n""const int KernelSize = 9; \n""uniform vec2 Offset[KernelSize]; \n""uniform vec4 KernelValue[KernelSize]; \n" "uniform sampler2DRect LenaTexture; \n""void main() \n""{ \n""vec2 pos = vec2(gl_TexCoord[0].s,512.0-gl_TexCoord[0].t);\n""int i; \n""vec4 sum = vec4(0.0); \n""for ( i = 0; i < KernelSize; ++i ) \n""{ \n"" vec4 tmp = texture2DRect(LenaTexture,pos + Offset[i]); \n"" sum += tmp * KernelValue[i]; \n""} \n" "gl_FragColor = sum; \n""} \n"};//打印错误信息int printOglError(char *file, int line){GLenum glErr;int retCode = 0;glErr = glGetError();while (glErr != GL_NO_ERROR){printf("glError in file %s @ line %d: %s\n", file, line, gluErrorString(glErr));retCode = 1;glErr = glGetError();}return retCode;}//打印openGL出错信息void printInfoLog(GLhandleARB obj){int infologLength = 0;int charsWritten = 0;GLcharARB *infoLog;printOpenGLError();glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB, &infologLength);printOpenGLError();if(infologLength > 0){infoLog = (GLcharARB*)malloc(infologLength);if(infoLog == NULL){printf("ERROR: Could not allocate InfoLog buffer\n");exit(1);}glGetInfoLogARB(obj,infologLength,&charsWritten,infoLog);printf("InfoLog:\n%s\n\n",infoLog);free(infoLog);}printOpenGLError();}/*************************************************************function name: initShadersinput: 1. const char *vShaderCode, 2. const char *fShaderCode,output: 1. -1 compile error 2. -2 link error 3. progHandle description:编译连接并使用着色器程序,输入为上面定义的char*型数组 输出就是一个可用的着色器句柄,返回的句柄主要为了初始化 内置的uniform变量,检查内部错误的用途 *****************************************************************/GLhandleARB initShaders( const char *vShaderCode, const char *fShaderCode ) //改为初始化的函数{GLhandleARB vertHandle, fragHandle, progHandle; //对象句柄GLint vertCompiled, fragCompiled;//状态值GLint linked;//创建顶点着色器对象和片元着色器对象vertHandle = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);fragHandle = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);//将源代码字符串加载到着色器中glShaderSource( vertHandle, 1, &vShaderCode, NULL );glShaderSource( fragHandle, 1, &fShaderCode, NULL );printf("编译码块顶点着色器并打印编译器日志文件:\n");//编译码块顶点着色器并打印编译器日志文件glCompileShaderARB(vertHandle);printOpenGLError();//检查opengl错误glGetObjectParameterivARB(vertHandle,GL_OBJECT_COMPILE_STATUS_ARB, &vertCompiled);printInfoLog(vertHandle);printf("编译码块片元着色器并打印编译器日志文件:\n");//编译码块片元着色器并打印编译器日志文件glCompileShaderARB(fragHandle);printOpenGLError(); //检查opengl错误glGetObjectParameterivARB(fragHandle,GL_OBJECT_COMPILE_STATUS_ARB, &fragCompiled);printInfoLog(fragHandle);if(!vertCompiled || !fragCompiled)return -1;//创建一个程序对象并附加两个编译好的着色器progHandle = glCreateProgramObjectARB();glAttachObjectARB(progHandle, vertHandle);glAttachObjectARB(progHandle, fragHandle);printf("链接程序对象并打印信息日志:\n");//链接程序对象并打印信息日志glLinkProgramARB(progHandle);printOpenGLError(); //检查opengl错误glGetObjectParameterivARB(progHandle, GL_OBJECT_LINK_STATUS_ARB, &linked);printInfoLog(progHandle);if(!linked)return -2;//将程序对象安装为当前状态的一部分glUseProgramObjectARB(progHandle); //改为运行的函数,用于测试该算法的时间 return progHandle;}//读入一个bmp图像作为纹理,对bmp图像的高斯滤波就是对这个纹理做滤波int LoadBmpAsTexture(char *textureFilePath, GLuint &texID ){unsigned char *pTexData = NULL;//指向数据的指针long bitCnt = 0;long iw =0;long ih = 0;long status = LoadBMP( textureFilePath, &pTexData,&iw, &ih, &bitCnt ); glGenTextures( 1, &texID );glBindTexture(GL_TEXTURE_RECTANGLE_ARB,texID);//当卷积内核超过了图像边界时使用图像边缘的像素值glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );glTexParameteri( GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );//纹理过滤的方式不应该设置为线性插值glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_NEAREST);glTexImage2D( GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, imgWidth, imgHeight, 0,GL_RGB,GL_UNSIGNED_BYTE,pTexData ); glTexEnvi( GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE ); return 0;}void init(){glShadeModel( GL_FLAT );glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );glViewport(0,0, imgWidth, imgHeight );glEnable ( GL_DEPTH_TEST );}void display( void ){glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );// glEnable( GL_TEXTURE_2D);//注意:要想使用着色器,一定不能激活纹理!!glBindTexture(GL_TEXTURE_2D,texture);//纹理坐标的设置glBegin( GL_QUADS ); glTexCoord2f( 0.0, 0.0); glVertex2f( -1.0, -1.0); glTexCoord2f( 0.0, imgHeight); glVertex2f( -1.0, 1.0 );glTexCoord2f( imgWidth, imgHeight ); glVertex2f( 1.0, 1.0 );glTexCoord2f( imgWidth, 0.0 ); glVertex2f ( 1.0, -1.0 );glEnd( );glFlush();}void PerformComputation(){LoadBmpAsTexture("texture.bmp",texture );display();}int _tmain(int argc, char* argv[]){GLhandleARB progHandle = 0;//偏移数组float offset[18]={-1,-1,-1,0,1,1,-1,0,0,0,1,0,1,-1,1,0,1,1};//高斯核float kernelValue[36]={0.0625,0.0625,0.0625,0.0625,0.125,0.125,0.125,0.125,0.0625,0.0625,0.0625,0.0625,0.125,0.125,0.125,0.125,0.25,0.25,0.25,0.25,0.125,0.125,0.125,0.125,0.0625,0.0625,0.0625,0.0625,0.125,0.125,0.125,0.125,0.0625,0.0625,0.0625,0.0625};glutInit( &argc, argv );glutInitDisplayMode( GLUT_SINGLE| GLUT_LUMINANCE);glutInitWindowSize ( imgWidth, imgHeight);glutInitWindowPosition( 100, 100 );glutCreateWindow(" gningh高斯滤波 ");glewInit();init();progHandle = initShaders(vShader, fShader); if ( progHandle <= 0 )printf("Failed to run shader.\n");else{//设置初始一致变量glUniform1i( glGetUniformLocation( progHandle, "LenaTexture" ), 0 ); //0 是纹理的句柄glUniform4fv( glGetUniformLocation( progHandle, "KernelValue"),9,kernelValue);glUniform2fv( glGetUniformLocation( progHandle, "Offset"),9,offset);}PerformComputation(); glutMainLoop();return 0;}
处理前的图像为:
高斯滤波后的图像为:
其实高斯滤波的模板可以换为拉普拉斯的模板,均值的模板等等~~这样就可以并行处理图像了
- GLSL着色器实现高斯滤波代码
- 着色器glsl
- glsl 细分着色器
- GLSL橙宝书中简单的着色器代码
- 场景中多个点光源的着色器GLSL代码
- GLSL-使用Uniform Block实现着色器的数据共享
- GLSL 透视变换(着色器实现C语言)
- 高斯滤波及canny边缘检测代码实现
- openCV之高斯滤波(及代码实现)
- 基于opencv的高斯滤波实现的VC++代码
- GLSL(着色器语言)
- opengl编程glsl-着色器
- 图像平滑技术之盒滤波、均值滤波、中值滤波、高斯滤波、双边滤波的原理概要及OpenCV代码实现
- 高斯滤波 openCV实现
- 高斯滤波 openCV实现
- DirectX11 使用计算着色器实现高斯模糊
- GLSL教程 OpenGL Setup for GLSL 创建着色器
- GLSL教程 OpenGL Setup for GLSL 创建着色器程序
- hdu2896(ac自动机)
- C#使用Ms Chart 实现饼图
- ural 1024. Permutations (置换群)
- Wall Time
- Howto Red hat enterprise Linux 5 configure the network card
- GLSL着色器实现高斯滤波代码
- OpenCV中OpenCL模块函数
- Union All/Union/Intersect操作
- 线索二叉树
- ASO技巧详解(3):截图等因素对ASO的影响
- linux内核移植-移植2.6.35.4内核到s3c2440
- 索引的用法
- 马尔科夫随机场(Markov Random Field)的概念与应用(一)
- 浅谈网站采集与SEO的秘密所在