顶点着色器VertexShader.txt:

uniform vec3 lightposition;//光源位置
uniform vec3 eyeposition;//相机位置
uniform vec4 ambient;//环境光颜色
uniform vec4 lightcolor;//光源颜色
uniform float Ns;//高光系数
uniform float attenuation;//光线的衰减系数
varying vec4 color;//向片段着色其传递的参数 void main()
{
vec3 ECPosition = vec3(gl_ModelViewMatrix * gl_Vertex);
vec3 N = normalize(gl_NormalMatrix * gl_Normal);
vec3 L = normalize(lightposition - ECPosition);
vec3 V = normalize(eyeposition - ECPosition);
vec3 H = normalize(V + L); vec3 diffuse = lightcolor * max(dot(N , L) , 0);
vec3 specular = lightcolor * pow(max(dot(N , H) , 0) , Ns) * attenuation; color = vec4(clamp((diffuse + specular) , 0.0 , 1.0) , 1.0);
color = color + ambient; gl_Position = ftransform();
}

片段着色器FragmentShader.txt:

varying vec4 color;
void main()
{
gl_FragColor = color;
}

完整程序:

#include <GL/glew.h>
#include <GL/freeglut.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #pragma comment(lib,"glew32.lib") using namespace std; GLfloat lightPosition[3] = { 30.0,30.0,30.0 };
GLfloat ambient[4] = { 0.0 , 0.0 , 1.0 , 1.0 };
GLfloat lightcolor[4] = { 1.0 , 1.0 , 1.0 , 1.0 };
GLfloat eyeposition[3] = { 0.0 , 10.0 , 30.0 };
GLfloat Ns = 30;
GLfloat attenuation = 0.01;
GLfloat objectSize = 15.0;
GLuint programHandle;
GLuint vShader, fShader; //读入字符流
char *textFileRead(const 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 initShader(const char *VShaderFile, const char *FShaderFile)
{
//1、查看显卡、GLSL和OpenGL的信息
const GLubyte *vendor = glGetString(GL_VENDOR);
const GLubyte *renderer = glGetString(GL_RENDERER);
const GLubyte *version = glGetString(GL_VERSION);
const GLubyte *glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
cout << "显卡供应商 : " << vendor << endl;
cout << "显卡型号 : " << renderer << endl;
cout << "OpenGL版本 : " << version << endl;
cout << "GLSL版本 : " << glslVersion << endl;
//2、编译着色器
//创建着色器对象:顶点着色器
vShader = glCreateShader(GL_VERTEX_SHADER);
//错误检测
if (0 == vShader)
{
cerr << "ERROR : Create vertex shader failed" << endl;
exit(1);
}
//把着色器源代码和着色器对象相关联
const GLchar *vShaderCode = textFileRead(VShaderFile);
const GLchar *vCodeArray[1] = { vShaderCode }; //将字符数组绑定到对应的着色器对象上
glShaderSource(vShader, 1, vCodeArray, NULL); //编译着色器对象
glCompileShader(vShader); //检查编译是否成功
GLint compileResult;
glGetShaderiv(vShader, GL_COMPILE_STATUS, &compileResult);
if (GL_FALSE == compileResult)
{
GLint logLen;
//得到编译日志长度
glGetShaderiv(vShader, GL_INFO_LOG_LENGTH, &logLen);
if (logLen > 0)
{
char *log = (char *)malloc(logLen);
GLsizei written;
//得到日志信息并输出
glGetShaderInfoLog(vShader, logLen, &written, log);
cerr << "vertex shader compile log : " << endl;
cerr << log << endl;
free(log);//释放空间
}
} //创建着色器对象:片断着色器
fShader = glCreateShader(GL_FRAGMENT_SHADER);
//错误检测
if (0 == fShader)
{
cerr << "ERROR : Create fragment shader failed" << endl;
exit(1);
} //把着色器源代码和着色器对象相关联
const GLchar *fShaderCode = textFileRead(FShaderFile);
const GLchar *fCodeArray[1] = { fShaderCode };
glShaderSource(fShader, 1, fCodeArray, NULL); //编译着色器对象
glCompileShader(fShader); //检查编译是否成功
glGetShaderiv(fShader, GL_COMPILE_STATUS, &compileResult);
if (GL_FALSE == compileResult)
{
GLint logLen;
//得到编译日志长度
glGetShaderiv(fShader, GL_INFO_LOG_LENGTH, &logLen);
if (logLen > 0)
{
char *log = (char *)malloc(logLen);
GLsizei written;
//得到日志信息并输出
glGetShaderInfoLog(fShader, logLen, &written, log);
cerr << "fragment shader compile log : " << endl;
cerr << log << endl;
free(log);//释放空间
}
}
//3、链接着色器对象
//创建着色器程序
programHandle = glCreateProgram();
if (!programHandle)
{
cerr << "ERROR : create program failed" << endl;
exit(1);
}
//将着色器程序链接到所创建的程序中
glAttachShader(programHandle, vShader);
glAttachShader(programHandle, fShader);
//将这些对象链接成一个可执行程序
glLinkProgram(programHandle);
//查询链接的结果
GLint linkStatus;
glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus);
if (GL_FALSE == linkStatus)
{
cerr << "ERROR : link shader program failed" << endl;
GLint logLen;
glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH,
&logLen);
if (logLen > 0)
{
char *log = (char *)malloc(logLen);
GLsizei written;
glGetProgramInfoLog(programHandle, logLen,
&written, log);
cerr << "Program log : " << endl;
cerr << log << endl;
}
}
} //完成glew初始化和加载顶点、片段着色器
void init()
{
//初始化glew扩展库
GLenum err = glewInit();
if (GLEW_OK != err)
{
cout << "Error initializing GLEW: " << glewGetErrorString(err) << endl;
}
glEnable(GL_DEPTH_TEST);
//加载顶点和片段着色器对象并链接到一个程序对象上
initShader("VertexShader.txt", "FragmentShader.txt"); glClearColor(0.0, 0.0, 0.0, 0.0);
} void Reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90, 1, 0.1, 1000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(eyeposition[0], eyeposition[1], eyeposition[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
} void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glUseProgram(programHandle);
glUniform3f(glGetUniformLocation(programHandle, "lightposition"), lightPosition[0], lightPosition[1], lightPosition[2]);
glUniform3f(glGetUniformLocation(programHandle, "eyeposition"), eyeposition[0], eyeposition[1], eyeposition[2]);
glUniform4f(glGetUniformLocation(programHandle, "ambient"), ambient[0], ambient[1], ambient[2], ambient[3]);
glUniform4f(glGetUniformLocation(programHandle, "lightcolor"), lightcolor[0], lightcolor[1], lightcolor[2], lightcolor[3]);
glUniform1f(glGetUniformLocation(programHandle, "Ns"), Ns);
glUniform1f(glGetUniformLocation(programHandle, "attenuation"), attenuation); glutSolidTeapot(objectSize);
//glutSolidSphere(objectSize-3, 100, 100);
glutSwapBuffers();
} void SpecialKey(GLint key, GLint x, GLint y)
{
if (key == GLUT_KEY_UP)
{
//do something
}
display();
} int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow("Hello GLSL");
init();
glutReshapeFunc(Reshape);
glutDisplayFunc(display);
glutSpecialFunc(SpecialKey);
glutMainLoop();
return 0;
}

执行效果:

再绘制一个实心球体:

OpenGL中GLSL渲染茶壶光照完整程序的更多相关文章

  1. OpenGL中的渲染方式—— GL_TRIANGLE_STRIP

    OpenGL值绘制三角形的方式常用的有三种,分别是GL_TRIANGLES.GL_TRIANGLE_STRIP.GL_TRIANGLE_FAN,其效果如依次是: 从左起:第一个方式是GL_TRIANG ...

  2. 通过OpenGL理解前端渲染原理(1)

    一.OpenGL OpenGL,是一套绘制3D图形的API,当然它也可以用来绘制2D的物体.OpenGL有一大套可以用来操作模型和图片的函数,通常编写OpenGL库的人是显卡的制造者.我们买的显卡都支 ...

  3. OpenGL中的拾取模式( Picking)

    1. Opengl中的渲染模式有三种:(1)渲染模式,默认的模式:(2)选择模式, (3)反馈模式.如下 GLint glRenderMode(GLenum mode) mode可以选取以下三种模式之 ...

  4. OpenGl中使用着色器的基本步骤及GLSL渲染简单示例

    OpenGL着色语言(OpenGL Shading Language,GLSL)是用来在OpenGL中着色编程的语言,是一种具有C/C++风格的高级过程语言,同样也以main函数开始,只不过执行过程是 ...

  5. GLSL 在OpenGL中向shader传递信息【转】

    http://blog.csdn.net/hgl868/article/details/7872219 引言 一个OpenGL程序可以用多种方式和shader通信.注意这种通信是单向的,因为shade ...

  6. 【GLSL教程】(三)在OpenGL中向shader传递信息 【转】

    http://blog.csdn.net/racehorse/article/details/6634830 引言 一个OpenGL程序可以用多种方式和shader通信.注意这种通信是单向的,因为sh ...

  7. 【GLSL教程】(二)在OpenGL中使用GLSL 【转】

    http://blog.csdn.net/racehorse/article/details/6616256 设置GLSL 这一节讲述在OpenGL中配置GLSL,假设你已经写好了顶点shader和像 ...

  8. CSharpGL(26)在opengl中实现控件布局/渲染文字

    CSharpGL(26)在opengl中实现控件布局/渲染文字 效果图 如图所示,可以将文字.坐标轴固定在窗口的一角. 下载 CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入( ...

  9. OpenGL中的光照技术(翻译)

    Lighting:https://www.evl.uic.edu/julian/cs488/2005-11-03/index.html 光照 OpenGL中的光照(Linghting)是很重要的,为什 ...

随机推荐

  1. iOS图片加载-SDWebImage

    一.SDWebImage内部实现过程 1, 入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后  SDWeb ...

  2. Vertx简介

    今天看了一篇很不错的关于Vertx的简介,转载下. 原文链接:http://www.csdn.net/article/2015-12-21/2826533?utm_source=tuicool& ...

  3. VS2012 打包部署程序

      一. 下载 InstallShield 2015(支持VS2012) VS2012没有自带打包工具,所以要先下载并安装一个打包工具.我采用微软提供的打包工具:  InstallShield2015 ...

  4. 你说你会C++? —— 智能指针

    智能指针的设计初衷是:      C++中没有提供自己主动回收内存的机制,每次new对象之后都须要手动delete.稍不注意就memory leak. 智能指针能够解决上面遇到的问题. C++中常见的 ...

  5. JAVA日志库2

    一.常用日志Jar关系 2015第30周四Java日志组件 接口:将所有日志实现适配到了一起,用统一的接口调用. 实现:目前主流的日志实现 旧日志到slf4j的适配器:如果使用了slf4j,但是只想用 ...

  6. Android Studio2.0 Beta 2版本号更新说明及注意事项

    我们刚刚向canary channel推送了Android Studio2.0 Beta 2版本号 老毕译注: ---------- canary channel: 金丝雀版本号,平均1到2周就会更新 ...

  7. [Angular2 Form] Reactive form: valueChanges, update data model only when form is valid

    For each formBuild, formControl, formGroup they all have 'valueChanges' prop, which is an Observable ...

  8. UTC、GTC时间和本地时间(Linux默认使用UTC时间,要修改一下)

    1.问题 对于装有Windows和Linux系统的机器,进入Windows显示的时间和Linux不一致,Linux中的时间比Windows提前8个小时. 2.解决方法 修改/etc/default/r ...

  9. USB 3.0规范中译本 第2章 术语及缩略语

    本文为CoryXie原创译文,转载及有任何问题请联系cory.xie#gmail.com. 本章列出并定义本规范通篇将使用的术语及缩略语. 术语/略缩语 定义 ACK(确认包) 表示积极肯定的握手包. ...

  10. 在RedHa上安装MRTG监控网卡流量

    http://os.51cto.com/art/201103/252149.htm 2011-03-30 15:05 张微波 phpchina 字号:T | T 在RedHa上安装MRTG监控网卡流量 ...