因为深度测试要拿甜甜圈去做演示,所以代码如下
#include "GLTools.h"
#include "GLMatrixStack.h"
#include "GLFrame.h"
#include "GLFrustum.h"
#include "GLGeometryTransform.h"
#include <math.h>
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
////设置角色帧,作为相机
//设置观察者位置
GLFrame viewFrame;
//使用GLFrustum类来设置透视投影
//设置图元绘制时的投影方式.
GLFrustum viewFrustum;
//三角形批次类
/*
批次类是帮我们管理和渲染图形,并且把数据传到固定管线里面的。
帮助类/容器类
*/
GLTriangleBatch torusBatch;
//模型视图矩阵
GLMatrixStack modelViewMatix;
//投影矩阵
GLMatrixStack projectionMatrix;
/*
变换管道.存储模型视图/投影/模型视图投影矩阵.
*/
GLGeometryTransform transformPipeline;
GLShaderManager shaderManager;
//标记:背面剔除、深度测试
int iCull = 0;
int iDepth = 0;
//渲染场景
//屏幕发生改变 都会掉RenderScene
void RenderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//1. viewFrumpush 到 模型视图里面
modelViewMatix.PushMatrix(viewFrame);
//2 设置画笔颜色
GLfloat vRed[] = {1.0f,0.0,0.0,1};
//3. 使用着色器了
/**
让我们在OpenGL使用矩阵
绘制默认OpenGL坐标系(-1,1)下图形,图形所有片段都会以一种颜色填充。
@param GLT_SHADER_FLAT 平面着色器
@param transformPipeline 里面会计算 模型矩阵和视图矩阵 相乘的结果 是一个管理类
@return MVP
*/
// shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vRed);
shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vRed);
torusBatch.Draw();
//pop
modelViewMatix.PopMatrix();
//提交渲染
glutSwapBuffers();
}
//负责图形相关的初始化
void SetupRC()
{
//设置背景颜色
glClearColor(0.3f, 0.3f, 0.3f, 1);
shaderManager.InitializeStockShaders();
//移动深度 移动Z值 往里移动负的, 往外移动正的,
viewFrame.MoveForward(7.0f);
//图片相关顶点
//顶点一般开发者不管,有设计师给你,甜甜圈模型有专门的API
//
/**
初始化花托的顶点批次
甜甜圈的API
@param torusBatch 批次类
@param majorRadius#> 内半径 description#>
@param minorRadius#> 外半径 description#>
@param numMajor#> 三角形个数 description#>
@param numMinor#> 细密成都 description#>
@return
*/
gltMakeTorus(torusBatch, 1.0f, 0.3f, 52, 26);
//3 点 线 面的方式 d填充
//4 线的宽度
glPointSize(4.0f);
}
//键位设置,通过不同的键位对其进行设置
//控制Camera的移动,从而改变视口
void SpecialKeys(int key, int x, int y)
{
if (key == GLUT_KEY_UP) {
viewFrame.RotateWorld(m3dDegToRad(-5.0f), 1, 0, 0);
}
if (key == GLUT_KEY_DOWN) {
viewFrame.RotateWorld(m3dDegToRad(5.0f), 1, 0, 0);
}
if (key == GLUT_KEY_LEFT) {
viewFrame.RotateWorld(m3dDegToRad(-5.0f), 0, 1, 0);
}
if (key == GLUT_KEY_RIGHT) {
viewFrame.RotateWorld(m3dDegToRad(5.0f), 0, 1, 0);
}
//重新渲染 GLTools 里面的函数
glutPostRedisplay();
}
//窗口改变
void ChangeSize(int w, int h)
{
//1.设置投影方式
glViewport(0, 0, w, h);
//2.设置投影方式 角度、纵横比 near flear 通过设置它来拿到投影矩阵
//拿到投影矩阵 viewFrustum.GetProjectionMatrix()
viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);
//3 加载到矩阵堆栈里面 矩阵堆栈只放一个元素的时候 跟数组里面放一个元素一样
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//4. 初始化模型矩阵 加载一个单元矩阵
/*
1,0,0
0,1,0
0,0,1
*/
modelViewMatix.LoadIdentity();
//5. 把 模型矩阵 和 视图矩阵 放进去 方便管理,可以拿到模型矩阵和视图矩阵
transformPipeline.SetMatrixStacks(modelViewMatix, projectionMatrix);
}
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("Geometry Test Program");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
}
SetupRC();
glutMainLoop();
return 0;
}
注意RenderScene()
里面的shaderManager.UseStockShader方法里面的第一个参数
GLT_SHADER_FLAT 平面着色器
绘制效果
GLT_SHADER_DEFAULT_LIGHT 默认光照着色器
绘制效果
光照会产生阴影,会产生正面和背面,而平面着色器不涉及光照,任何位置画出的图都是红色,有了光照才能区分正面和背面。