顶点着色器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. js课程 2-8 js内置对象有哪些

    js课程 2-8 js内置对象有哪些 一.总结 一句话总结:JS中内置了17个对象,常用的是Array对象.Date对象.正则表达式对象.string对象.Global对象. 1.js常用对象有哪些? ...

  2. 一、Github博客搭建之jekyll安装

    注意:以下步骤是FQ后操作的,需要了解FQ的可以移步 -> 枫叶主机 一.安装jekyll需要Ruby-2.1.0以上版本,本人是mac pro系统版本10.12.5(macOS Sierra) ...

  3. jQuery weui Select组件显示指定值

    jQuery weui有个支持单选或者多选的select弹出层,默认他是这样的 第2部分选择什么值,第1部分就显示什么值,一般的场景支持是没问题了,但本次开发碰到了一个问题. 需求描述: 职业名称后面 ...

  4. 使用RxPermissions(基于RxJava2)

    使用RxPermissions(基于RxJava2) 0. 背景 Android 6.0 (API level 23)中.将权限分成了两类.一类是Install权限(称之为安装时权限).还有一类是Ru ...

  5. nginx简介(轻量级开源高并发web服务器:大陆使用者百度、京东、新浪、网易、腾讯、淘宝等)(并发量5w)(一般网站apache够用了,而且稳定)

    nginx简介(轻量级开源高并发web服务器:大陆使用者百度.京东.新浪.网易.腾讯.淘宝等)(并发量5w)(一般网站apache够用了,而且稳定) 一.总结 1.在连接高并发的情况下,Nginx是A ...

  6. Android 闹钟最终版

    以下是我发现的几点闹钟中重要的点,分享一下: (1)在闹钟中有AudioManager管理机制,这个机制可以申请和释放OnAudioFocusChangeListener监听. 还有mTelephon ...

  7. php 字符串 去掉 html标签

    echo strip_tags("Hello <b>world!</b>");

  8. <Linux> Linux下一些常用命令(个人记录)

    mount -o loop XXXX  XXX ./XXX &   后台运行 rm -rf XXX  删除文件夹 rm -rf *  删除当前目录下的所有文件 包括文件夹 ps -ef | g ...

  9. js获取滚动条的宽度

    function getScrollWidth() { var noScroll, scroll, oDiv = document.createElement("DIV"); oD ...

  10. .NET-架构优化实战-前端优化

    原文:.NET-架构优化实战-前端优化 前言 上一篇<.NET-架构优化实战-梳理篇>整理了基本的业务知识,同时也罗列了存在的问题,本篇主要是针对任务列表的页面进行性能优化. 该篇主要涉及 ...