OpenGL蓝宝书源码学习(一)第二章——Triangle.cpp

一个简单的显示三角形的源码示例

// Triangle.cpp
// Our first OpenGL program that will just draw a triangle on the screen.

#include 
   
   
    
                // OpenGL toolkit
#include 
    
    
     
         // Shader Manager Class

#ifdef __APPLE__
#include 
     
     
      
                // OS X version of GLUT
#else
#define FREEGLUT_STATIC
#include 
      
      
       
                   // Windows FreeGlut equivalent
#endif

GLBatch	triangleBatch;
GLShaderManager	shaderManager;

///
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.
void ChangeSize(int w, int h)
    {
	glViewport(0, 0, w, h);
    }


///
// This function does any needed initialization on the rendering context. 
// This is the first opportunity to do any OpenGL related tasks.
void SetupRC()
	{
	// Blue background
	glClearColor(0.0f, 0.0f, 1.0f, 1.0f );
    
	shaderManager.InitializeStockShaders();

	// Load up a triangle
	GLfloat vVerts[] = { -0.5f, 0.0f, 0.0f, 
		                  0.5f, 0.0f, 0.0f,
						  0.0f, 0.5f, 0.0f };

	triangleBatch.Begin(GL_TRIANGLES, 3);
	triangleBatch.CopyVertexData3f(vVerts);
	triangleBatch.End();
	}



///
// Called to draw scene
void RenderScene(void)
	{
	// Clear the window with current clearing color
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
	shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
	triangleBatch.Draw();

	// Perform the buffer swap to display back buffer
	glutSwapBuffers();
	}


///
// Main entry point for GLUT based programs
int main(int argc, char* argv[])
	{
	gltSetWorkingDirectory(argv[0]);
	
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
	glutInitWindowSize(800, 600);
	glutCreateWindow("Triangle");
    glutReshapeFunc(ChangeSize);
    glutDisplayFunc(RenderScene);

	GLenum err = glewInit();
	if (GLEW_OK != err) {
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
		return 1;
		}
	
	SetupRC();

	glutMainLoop();
	return 0;
	}
      
      
     
     
    
    
   
   

一、先看头文件

GLTools.h头文件中包含了大部分GLTools中类似C语言的独立函数,而每个GLTools的C++类则有自己的头文件。例如在本示例中用到的GLBatch类型,在次GLTools.h包含了GLBatch.h,使用GLBatch类对顶点、颜色、法线等数据进行设置时,这些数据都是存储在CPU中。这个简单的封装类会将顶点等数据批次进行封装可下载GLTools源码查看其中的源文件,在学习过程中,慢慢介绍。
GLShaderManager.h移入了GLTools着色器管理器(Shader Manager)类。没有着色器,我们就不能在OpenGL(核心框架)中进行着色。
在Windows和Linux上,我们使用freeglut的静态库版本,所以在它前面添加FREEGLUT_STATIC处理器宏。

二、关键源码解析

1、int main(int argc, char* argv[])


在Win32中,我们可以从控制台应用程序建立图形窗口,GLUT库隐藏了这些细节。


gltSetWorkingDirectory(argv[0]);  用来设置当前工作目录,在GLTools.h中定义

glutInit(&argc, argv);  初始化GLUT库


glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);

标志一次表示:使用双缓冲窗口;RGBA颜色模式;支持深度缓冲区;支持模版缓冲区。


glutInitWindowSize(800, 600);
glutCreateWindow("Triangle");

初始化GLUT窗口的大小设置,并创建以“Triangle”为标题的窗口。


  glutReshapeFunc(ChangeSize);
     glutDisplayFunc(RenderScene);

     为窗口改变大小设置的回调函数,以便能够设置视点;注册函数以包含OpenGL渲染代码。


GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;

}

重新调用GLEW库初始化OpenGL驱动程序中所有丢失的入口点,以确保OpenGl API是完全可用的。


 SetupRC();RC代表渲染环境(Rendering Context), 这是一个运行中的OpenGl状态机的句柄


glutMainLoop();

此函数被调用后,在主窗口被关闭之前都不回返回,负责处理所有操作系统特定的消息、按键动作等,直到我们关闭程序为止。


    2、void ChangeSize(int w, int h)  在窗口大小改变是接受新的宽度和高度。

glViewport(0, 0, w, h);  参数0和0代表窗口中视口的左下角坐标,w和h代表宽度和高度是用像素表示的。OpenGL可以在这个区域中进行绘图的裁剪区域被映射到新的视口

3、void SetupRC()  在开始main函数中的GLUT主循环之前,我们先调用SetupRC,为程序做一些一次性的设置。

glClearColor(0.0f, 0.0f, 1.0f, 1.0f );
shaderManager.InitializeStockShaders();
用当前清除颜色来清除窗口,这个函数不会立即调用,而是设置在以后颜色缓冲区被清除时使用的颜色,并且清除颜色设置为蓝色;初始话渲染着色器;


GLfloat vVerts[] = { -0.5f, 0.0f, 0.0f, 
                                  0.5f, 0.0f, 0.0f,
     0.0f, 0.5f, 0.0f };
        triangleBatch.Begin(GL_TRIANGLES, 3);
          triangleBatch.CopyVertexData3f(vVerts);   
triangleBatch.End();
       设置顶点,包含3个顶点的x、y、z笛卡尔坐标对,由于显示的是2D图形,z坐标都设置为0;对批次进行初始化,告诉这个类它代表哪种图元,其中包括的顶点数,以及(可选)一组或两组纹理坐标;复制一个由3分量(x,y,z)顶点组成的数组;调用End来表明已经完成了数据的复制工作,并且将设置内部标记,以通知这个类包含哪些属性,一旦End函数被调用,就不能再添加新的属性了。

4、void RenderScene(void)  更新窗口,只要窗口发生最小化、恢复、最大化、覆盖或重新显示等变化,就会更新。

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
触发在SetupRC函数中的清除函数glClear(),清除一个或一组特定的缓冲区。缓冲区是一块存储图形信息的存储空间。(缓冲区后面继续学习!)


GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
triangleBatch.Draw();
设置渲染颜色;选择一个存储着色器并提供这个着色器的Uniform值(文章后面简单介绍这些着色器);指示将几何图形提交到着色器。


glutSwapBuffers();
在main函数开始时设置了双缓冲窗口,我们在后台缓冲区进行渲染,当在结束时交换到前台。这种形式能够防止观察者看到动画帧与动画帧之间闪烁的渲染过程。

OK!第一个实例代码就到这,下面简单学习一下着色器!


三、着色器简单学习

GLShaderManager::UseStackShader(GLenum shader,......);

在C语言(C++)中,.......表示函数接受一个可变的参数数量。就函数本身而言,它根据我们选择的着色器从堆栈中提取正确的参数,这些参数就是特定着色器要求的Uniform值

1、单位(Identity)着色器

只是简单地使用默认的笛卡尔坐标。只使用一个属性GLT_ATTRIBUTE_VERTEX,vColor参数包含了要求的颜色

GLShaderManager::UseStockShader(GLT_SHADER_IDENTITY,GLFloat vColor[4]);

        2、平面(Flat)着色器

平面着色器将统一着色器进行了扩展,允许为几何图形变换指定一个4X4的变换矩阵。典型情况下是一种左乘模型视图矩阵和投影矩阵,通常称作“模型视图投影矩阵”。这种着色器只使用一个属性GLT_ATTRIBUTE_VERTEX。

GLSahderManager::UseStockShader(GLT_SHADER_FLAT,GLfloat mvp[16],GLfloat vColor[4]);

3、上色(Shaded)着色器

这种着色器唯一的Uniform值就是在几何图形中应用的变换矩阵。GLT_ATTRIBUTE_VERTEX和GLT_ATTRIBUTE_COLOR在这种着色器中都会使用。颜色值将被平滑地插入到顶点之间(称为平滑着色)。

GLSahderManager::UseStockShader(GLT_SHADER_SHADED,GLfloat mvp[16]);

4、默认光源着色器

本质上讲,这种着色器使对象产生阴影和光照的效果。需要模型视图矩阵、投影矩阵和作为基本色的颜色值等Uniform值。所需的属性有GLT_ATTRIBUTE_VERTEX和GLT_ATTRIBUTE_NORMAL。大多数光照着色器都需要正规矩阵作为Uniform值。

   GLShaderManager::UseStock(GLT_DEFAULT_LIGHT,GLfloat mvMatrix[16],GLfloat pMaxtrix[16],GLfloat vColor[4]);

5、点光源着色器

光源位置可能是特定的。接受4个Uniform值,即模型视图矩阵、投影矩阵、视点坐标系中的光源位置和对象的基本漫反射颜色。所需的属性有GLT_ATTRIBUTE_VERTEX和GLT_ATTRIBUTE_NORMAL

GLShaderManager::UserStockShader(GLT_SHADER_POINT_LIGHT_DIFF,GLfloat mvMaxtrix[16],GLfloat pMaxtrix[16],GLflaoat vLightPos[3],GLfloat vColor[4]);

6、纹理替换矩阵

通过给定的模型视图投影矩阵,使用绑定到nTextureUnit指定的纹理单元的纹理对几何图形进行变换。片段颜色是直接从纹理样本中直接获取的。所需的属性有GLT_ATTRIBUTE_VERTEX和GLT_ATTRIBUTE_NORMAL。

GLShaderManager::UseStockShader(GLT_SHADER_TEXTURE_REPLACE,GLfloat mvpMatrix[16],GLint nTextureUnit);

7、纹理调整着色器

这种着色器将一个基本色乘以一个取自纹理单元nTextureUnit的纹理。所需的属性有GLT_ATTRIBUTE_VERTEX和GLT_ATTRIBUTE_TEXTURE0.

GLShaderManager::UseStockShader(GLT_SHADER_TEXTURE_MODULATE,GLfloat mvpMatrix[16],GLfloat vColor,GLint nTextureUnit);

8、纹理光源着色器

将一个纹理通过漫反射照明计算进行调整(相乘),光线在视觉空间中的位置是给定的。这种着色器接受5个Uniform值,即模型视图矩阵、投影矩阵、视觉空间中的光源位置、几何图形的基本色和将要使用的纹理单元。所需的属性有GLT_ATTRIBUTE_VERTEX、GLT_ATTRIBUTE_NORMAL和GLT_ATTRIBUTE_TEXTURE0.

GLShaderManager::UseStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF,
GLfloat mvMatrix,GLfloat pMatrix[16],GLfoat vLightPos[3],
GLfloat vBaseColor[4], GLint nTextureUnit);

后面继续源码的学习!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值