许世鑫

来自CGTWiki
跳转至:导航搜索

个人简介

许世鑫
2017级    河北大学        网络空间安全与计算机学院   信息安全   本科
2021级    北京邮电大学          电子工程学院         电子信息   硕士

研究方向:三维显示与信息处理、多媒体信息处理
四级:517 六级:470
Email:1594789533@qq.com
Tel:13191739245
微信:Apr-20-99

学习内容

11月1日

  • 建立一个易于管理的C++工程
管理不同配置的相关设置:
输出目录:$(SolutionDir)../bin/$(Platform)/$(Configuration)
中间目录:$(SolutionDir)../temp/$(Platform)/$(Configuration)/$(ProjectName)
  • VS C++程序常用调试方法
①打印数据来调试程序
②普通断点
③条件断点
④条件追踪
⑤单步调试
⑥添加监视
//打印数据方式
#include<stdio.h>

int main()
{
	int a = 0;
	for (int i = 1; i <= 10; i++)
	{
		a = a + i;
#ifdef _DEBUG //宏定义不影响实际要发布代码
		if (i == 5)
			printf("debug: i==5,a=%d \n", a);
#endif // _DEBUG
	}
	printf("a=%d \n", a);
}

11月2日

  • 一级指针以及二级指针用法:
一级指针可以用来指向变量的地址来对变量进行任意操作,二级指针就是来指向一级指针并对一级指针进行任意操作的。以此类推,三级指针,四级..
#include <stdio.h>

// 交换两个变量的值
void swap(int *x, int *y)
{
	int temp;
	temp = *x;
	*x = *y;
	*y = temp;
}
int main()
{
	int a = 10, b = 5;
	int *pa = &a, *pb = &b;

	//&pa自身地址,pa他所指向的地址,*pa他所指向的地址的值,**ppa指向pa的自身地址,
	int **ppa = &pa, **ppb = &pb;    // 加了两个二级指针来指向pa和pb自己的地址
	//ppa指向pa的地址,*ppa指向pa所指向的地址,**ppa表pa指向地址的值,和*pa等价
	swap(*ppa, *ppb);    // *ppa和*ppb指向了pa和pb指向的变量a和b的地址

	printf("a=%d\tb=%d\n", a, b);
	printf("%d\n", **ppa);    // 5
}
  • 数组指针和指针数组
数组指针是一个指向数组的指针,可以通过单个指针来完成对整个数组进行遍历。而指针数组则是一些指针组成的数组。
#include <stdio.h>
//数组指针实例
int main()
{
	int arr[5] = { 8, 6, 4, 1, 4 };    // 定义一个长度为5的int类型数组
	int *pArr = arr; 
	int i;
	*pArr = 10;    // 将数组中第一个元素修改成10
	*(pArr + 2) = 13;    // 将数组中第3个元素修改成13

	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
	{
		printf("%d\t", *(pArr + i));    // 10    6    13    1    4
	}
	return 0;
}
#include <stdio.h>
//指针数组实例
int main()
{
	int arr[5] = { 8, 6, 4, 1, 4 };    // 定义一个长度为5的int类型数组
	int *pArr[5]; 
	int i;
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
	{
		pArr[i] = &arr[i];    // 将数组中每个元素依次对应指针数组中的每个指针
	}
	*pArr[0] = 10;    // 将数组中第一个元素修改成10
	*pArr[2] = 13;    // 将数组中第3个元素修改成13
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
	{
		printf("%d\t", *pArr[i]);    // 10      6       13      1       4
	}
	return 0;
}
  • 指针常量和指针常量
'''指针常量'''无法修改自己已经指向的地址,但可以修改所指向地址的值。
'''常量指针'''无法修改自己所指向的地址的值,但可以修改自己所指向的地址。
#include <stdio.h>
//指针常量实例
int main()
{
	int a,b;
	int * const p = &a; 
	  //分为一下两种操作
		*p = 9;//操作成功
		printf("%d\t", *p);
	    // p = &b;//操作错误
}
#include <stdio.h>
//常量指针实例
int main()
{
	int a,b;
	a = 5;
	b = 8;
	const int *p = &a; 
	printf("%d\t", *p);
//分为以下两种操作
	//*p = 9;//操作错误
	p = &b;//操作成功
	printf("%d\t", *p);
}
  • 安装配置SVN版本控制管理工具
SVN工具核心功能:文档版本管理系统

11月3--4日

  • VMware虚拟机中安装Mac10.16、Ubuntu20.04操作系统

11月7日

  • 第一章:OpenGL环境建立
  • 创建win32窗口
注册窗口类
创建窗口
显示更新窗口
消息循环
HINSTANCE hInstance,//实例句柄,也可理解为实例(应用程序)的一个指针
HINSTANCE hPrevInstance,//前一个实例句柄
LPSTR lpCmdLine,//命令行
int nShowCmd,
wnd.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;//支持双击、水平重画、垂直重画、自己的DC,用来绘制的设备上下文
#include <windows.h>
#include <tchar.h>
//创建win32窗口

LRESULT CALLBACK wndProc(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
{
	switch(msgId)
	{
	case WM_CLOSE:
	case WM_DESTROY:
		{
			PostQuitMessage(0);
		}
		break;
	default:
		return DefWindowProc(hWnd,msgId,wParam,lParam);
	}
	return 0;
}

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	//1注册窗口类
	WNDCLASSEX wnd;

	memset(&wnd,0,sizeof(wnd));

	wnd.cbSize          =   sizeof(wnd); //指明当前结构体大小
	wnd.lpfnWndProc     =   wndProc; //函数指针,若有事件发生,则调此函数
	wnd.hbrBackground   =   (HBRUSH)GetStockObject(GRAY_BRUSH);
	wnd.hCursor         =   LoadCursor(hInstance,IDC_ARROW);//鼠标样式
	wnd.hIcon           =   0;
	wnd.hIconSm         =   0;
	wnd.hInstance       =   hInstance;
	wnd.lpszClassName   =   _T("lesson01"); 
	wnd.style           =   CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	RegisterClassEx(&wnd);  //调用注册窗口类函数
	//2创建窗口
	HWND hWnd  =   CreateWindowEx(
		0 // 窗口的扩展风格
		,_T("lesson01")//需和wnd.lpszClassName一致
		,_T("lesson01")//窗口标题
		,WS_OVERLAPPEDWINDOW//窗口风格,有无最大化最小化
		,100//窗口在屏幕的位置
		,100//窗口在屏幕的位置
		,480//宽
		,320//高
		,0//系统菜单
		,0//父窗口
		,hInstance//实例句柄
		,0);//用户数据
	//3更新显示
	if(hWnd)
	{
		UpdateWindow(hWnd);
		ShowWindow(hWnd,SW_SHOW);
	}

	MSG  msg={0};
	//4消息循环
	while(WM_QUIT !=msg.message)
	{
		if(GetMessage(&msg,0,0,0))//有消息产生;点关闭按钮,返回值为false
		{
			TranslateMessage(&msg);//翻译
			DispatchMessage(&msg);//分发
		}
	}
	return 0;
}
  • 编译时遇到问题:
  error LNK2019: 无法解析的外部符号 _main,该符号在函数 ___tmainCRTStartup 中被引用;
  window.exe : fatal error LNK1120: 1 个无法解析的外部命令
  • 正确解决:
  项目属性--配置属性--C/C++--链接器--系统--子系统


配置
运行结果





























11月8--9日

GetMessage():等待消息,如果没有消息就一直停在这
PeekMessage():等待消息,如果没有消息直接返回
#pragma once
//在win32窗口下建立OPenGL的开发环境
#include <Windows.h>
#include <tchar.h>

#include <gl/gl.h> 
//OpenGL的标准头文件

class GLContext
{
protected:
	int    _format;
	HWND   _hWnd; //窗口句柄
	HDC    _hDC;//绘制设备上下文
	HGLRC  _hRC;//OpenGL上下文
public:

	GLContext(void)
	{
       _format  =   0;
       _hWnd    =   0; 
       _hDC     =   0; 
       _hRC     =   0; 


	}

	~GLContext(void)
	{
		shutdown();
	}
//初始化GL
	bool setup(HWND hWnd,HDC hDC){
      _hWnd  =  hWnd;
      _hDC   =  hDC;
	  unsigned PixelFormat;
	  //像素的格式描述符
	  PIXELFORMATDESCRIPTOR pfd = 
	  {
         sizeof(PIXELFORMATDESCRIPTOR),
		 1,//版本,window支持1
		 PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |PFD_DOUBLEBUFFER,
		 PFD_TYPE_RGBA,//像素类型 不采用索引(4个通道,每个通道占8个bit位)
		 32,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 24,//深度缓冲区
		 8,//模板缓冲区
		 0,//累计缓存
		 PFD_MAIN_PLANE,//直接写到屏幕上
		 0,
		 0,
		 0,
		 0
	  };
	  if(_format == 0) //初始化
	  {
		  //得到索引
		  PixelFormat = ChoosePixelFormat(_hDC,&pfd); //在_hDC上匹配pfd
	  }
	  else
	  {
		  PixelFormat = _format;
	  }
	  if(!SetPixelFormat(_hDC,PixelFormat,&pfd))
	  {
		  return false;
	  }
	  //返回的OpenGL的上下文句柄
	  _hRC  =  wglCreateContext(_hDC); //在给定的DC上建立上下文
	  if(!wglMakeCurrent(_hDC,_hRC))
	  {
		  return false;
	  }
	  return true;
	}
//销毁EGL
	void shutdown(){
      if(_hRC != NULL)
	  {
		  wglMakeCurrent(NULL,NULL);
		  wglDeleteContext(_hRC);
		  _hRC=NULL;
	  }
	  if(_hDC != NULL)
	  {
		  ReleaseDC(_hWnd,_hDC);
		  _hDC=NULL;
	  }

	}
//交换缓冲区
	void swapBuffer(){
     SwapBuffers(_hDC);
	}
};

#include "GLContext.h"
//创建win32窗口

LRESULT CALLBACK wndProc(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
{
	switch(msgId)
	{
	case WM_CLOSE:
	case WM_DESTROY:
		{
			PostQuitMessage(0);
		}
		break;
	default:
		return DefWindowProc(hWnd,msgId,wParam,lParam);
	}
	return 0;
}

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	//1注册窗口类
	WNDCLASSEX wnd;

	memset(&wnd,0,sizeof(wnd));

	wnd.cbSize          =   sizeof(wnd); //指明当前结构体大小
	wnd.lpfnWndProc     =   wndProc; //函数指针,若有事件发生,则调此函数
	wnd.hbrBackground   =   (HBRUSH)GetStockObject(GRAY_BRUSH);
	wnd.hCursor         =   LoadCursor(hInstance,IDC_ARROW);//鼠标样式
	wnd.hIcon           =   0;
	wnd.hIconSm         =   0;
	wnd.hInstance       =   hInstance;
	wnd.lpszClassName   =   _T("lesson01"); 
	wnd.style           =   CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	RegisterClassEx(&wnd);  //调用注册窗口类函数
	//2创建窗口
	HWND hWnd  =   CreateWindowEx(
		0 // 窗口的扩展风格
		,_T("lesson01")//需和wnd.lpszClassName一致
		,_T("lesson01")//窗口标题
		,WS_OVERLAPPEDWINDOW//窗口风格,有无最大化最小化
		,100//窗口在屏幕的位置
		,100//窗口在屏幕的位置
		,480//宽
		,320//高
		,0//系统菜单
		,0//父窗口
		,hInstance//实例句柄
		,0);//用户数据
	//3更新显示
	if(hWnd)
	{
		UpdateWindow(hWnd);
		ShowWindow(hWnd,SW_SHOW);
	}
	else
	{
		return 0;
	}

    GLContext context;
	if(!context.setup(hWnd,GetDC(hWnd)))
	{
		return 0;
	}

	MSG  msg={0};
	//4消息循环
	while(WM_QUIT !=msg.message)
	{
		if(PeekMessage(&msg,0,0,0,PM_REMOVE))//有消息产生;点关闭按钮,返回值为false
		{
			TranslateMessage(&msg);//翻译
			DispatchMessage(&msg);//分发
		}
		else
		{
			/*调用绘制函数进行绘制*/
            glClearColor(1,1,1,1);//改变颜色
			glClear(GL_COLOR_BUFFER_BIT);//清空背景颜色
			context.swapBuffer();
		}
	}
	context.shutdown();
	return 0;
}
  • 遇到问题:

LINK : fatal error LNK1168: 无法打开 C:\Users\dell\Documents\Visual Studio 2008\Projects\lesson3-OpenGL\Debug\lesson3-OpenGL.exe 进行写入

  • 解决方法:

项目属性--配置属性--链接器--输入--附加依赖项,添加OpenGL32.lib

  • 运行结果:
运行















11月10日

  • MFC-对话框下建立OpenGL环境
属性配置:
项目属性--常规--输出目录:../../temp/$(ConfigurationName)/$(PlatformName)/$(ProjectName)
中间目录:../../temp/$(ConfigurationName)/$(PlatformName)/$(ProjectName)
链接器--输出文件:../../bin/$(ConfigurationName)$(PlatformName)/$(ProjectName).exe
链接器--输入--附加依赖项:OpenGL32.lib
  • 遇到问题:

LINK : fatal error LNK1000: Internal error during IncrBuildImage

  • 解决:

项目属性--配置属性--链接器--常规--启用增量连接:否(/INCREMENTAL:NO)

// lesson004-MFC-Dialog.cpp : 定义应用程序的类行为。
//

#include "stdafx.h"
#include "lesson004-MFC-Dialog.h"
#include "lesson004-MFC-DialogDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// Clesson004MFCDialogApp

BEGIN_MESSAGE_MAP(Clesson004MFCDialogApp, CWinApp)
	ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()


// Clesson004MFCDialogApp 构造

Clesson004MFCDialogApp::Clesson004MFCDialogApp()
{
	// TODO: 在此处添加构造代码,
	// 将所有重要的初始化放置在 InitInstance 中
}


// 唯一的一个 Clesson004MFCDialogApp 对象

Clesson004MFCDialogApp theApp;


// Clesson004MFCDialogApp 初始化

BOOL Clesson004MFCDialogApp::InitInstance()
{
	CWinApp::InitInstance();

	// 标准初始化
	// 如果未使用这些功能并希望减小
	// 最终可执行文件的大小,则应移除下列
	// 不需要的特定初始化例程
	// 更改用于存储设置的注册表项
	// TODO: 应适当修改该字符串,
	// 例如修改为公司或组织名
	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));

	Clesson004MFCDialogDlg dlg;
	m_pMainWnd = &dlg;
	INT_PTR nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: 在此放置处理何时用
		//  “确定”来关闭对话框的代码
	}
	else if (nResponse == IDCANCEL)
	{
		// TODO: 在此放置处理何时用
		//  “取消”来关闭对话框的代码
	}

	// 由于对话框已关闭,所以将返回 FALSE 以便退出应用程序,
	//  而不是启动应用程序的消息泵。
	return FALSE;
}
// lesson004-MFC-DialogDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "lesson004-MFC-Dialog.h"
#include "lesson004-MFC-DialogDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// Clesson004MFCDialogDlg 对话框




Clesson004MFCDialogDlg::Clesson004MFCDialogDlg(CWnd* pParent /*=NULL*/)
	: CDialog(Clesson004MFCDialogDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void Clesson004MFCDialogDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(Clesson004MFCDialogDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_WM_DESTROY()
END_MESSAGE_MAP()


// Clesson004MFCDialogDlg 消息处理程序

BOOL Clesson004MFCDialogDlg::OnInitDialog() //相当于对话框里的main函数
{
	CDialog::OnInitDialog();

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	HDC hDC  =  ::GetDC(m_hWnd);
    _context.setup(m_hWnd,hDC);

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void Clesson004MFCDialogDlg::OnPaint()
{
	glClearColor(1,0,0,1);//指定清空颜色
	glClear(GL_COLOR_BUFFER_BIT);//调用此函数才会真正实现上行清空颜色
    _context.swapBuffer();
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR Clesson004MFCDialogDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void Clesson004MFCDialogDlg::OnDestroy()
{
	_context.shutdown();//关闭文件夹对象
	CDialog::OnDestroy();

	// TODO: 在此处添加消息处理程序代码
}
// lesson004-MFC-DialogDlg.h : 头文件
//
#include "GLContext.h"

#pragma once


// Clesson004MFCDialogDlg 对话框
class Clesson004MFCDialogDlg : public CDialog
{
// 构造
public:
	Clesson004MFCDialogDlg(CWnd* pParent = NULL);	// 标准构造函数

// 对话框数据
	enum { IDD = IDD_LESSON004MFCDIALOG_DIALOG };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持

protected:
   GLContext _context;

// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnDestroy();
};
  • 运行结果:
运行














11月11日

  • 遇到问题:确认和取消按钮没有显示
  • 解决方法:调整控件:将Clip Children 改为True;将Clip Siblings 改为True
  • 运行结果:
运行















  • 遇到问题:拖动窗口有闪动
  • 原因:对话框在绘制时候要清空背景造成的
  • 解决方法:调整控件:添加WM_ERASEBKGND :

BOOL Clesson004MFCDialogDlg::OnEraseBkgnd(CDC* pDC) { return true; }

  • MFC-View搭建OpenGL环境
// lesson5-MFC-SDIView.cpp : Clesson5MFCSDIView 类的实现
//

#include "stdafx.h"
#include "lesson5-MFC-SDI.h"

#include "lesson5-MFC-SDIDoc.h"
#include "lesson5-MFC-SDIView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// Clesson5MFCSDIView

IMPLEMENT_DYNCREATE(Clesson5MFCSDIView, CView)

BEGIN_MESSAGE_MAP(Clesson5MFCSDIView, CView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
	ON_WM_DESTROY()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

// Clesson5MFCSDIView 构造/析构

Clesson5MFCSDIView::Clesson5MFCSDIView()
{
	// TODO: 在此处添加构造代码

}

Clesson5MFCSDIView::~Clesson5MFCSDIView()
{
}

BOOL Clesson5MFCSDIView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CView::PreCreateWindow(cs);
}

// Clesson5MFCSDIView 绘制

void Clesson5MFCSDIView::OnDraw(CDC* /*pDC*/)
{
	Clesson5MFCSDIDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: 在此处为本机数据添加绘制代码
    glClearColor(0,1,0,1);
	glClear(GL_COLOR_BUFFER_BIT);//只清空颜色缓冲区,其他不动
	_context.swapBuffer();
}


// Clesson5MFCSDIView 打印

BOOL Clesson5MFCSDIView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}

void Clesson5MFCSDIView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加额外的打印前进行的初始化过程
}

void Clesson5MFCSDIView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加打印后进行的清理过程
}


// Clesson5MFCSDIView 诊断

#ifdef _DEBUG
void Clesson5MFCSDIView::AssertValid() const
{
	CView::AssertValid();
}

void Clesson5MFCSDIView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

Clesson5MFCSDIDoc* Clesson5MFCSDIView::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(Clesson5MFCSDIDoc)));
	return (Clesson5MFCSDIDoc*)m_pDocument;
}
#endif //_DEBUG


// Clesson5MFCSDIView 消息处理程序

void Clesson5MFCSDIView::OnInitialUpdate() //类似于初始化对话框函数
{
	CView::OnInitialUpdate();

	// TODO: 在此添加专用代码和/或调用基类
	HDC  hDC  =  ::GetDC(m_hWnd);
	_context.setup(m_hWnd,hDC);
}

void Clesson5MFCSDIView::OnDestroy()
{
	CView::OnDestroy();

	// TODO: 在此处添加消息处理程序代码
	_context.shutdown();
	CView::OnDestroy();
	
}

BOOL Clesson5MFCSDIView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	return true;
}
  • 运行结果:
运行结果













  • MFC-MDI(多文档视图)下搭建OpenGL环境
单文档和多文档视图的区别:
单文档下只有一个OpenGL对象,多文档下有多个OpenGL对象
// lesson6-MFC-MDIView.cpp : Clesson6MFCMDIView 类的实现
//

#include "stdafx.h"
#include "lesson6-MFC-MDI.h"

#include "lesson6-MFC-MDIDoc.h"
#include "lesson6-MFC-MDIView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// Clesson6MFCMDIView

IMPLEMENT_DYNCREATE(Clesson6MFCMDIView, CView)

BEGIN_MESSAGE_MAP(Clesson6MFCMDIView, CView)
	// 标准打印命令
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
	ON_WM_DESTROY()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

// Clesson6MFCMDIView 构造/析构

Clesson6MFCMDIView::Clesson6MFCMDIView()
{
	// TODO: 在此处添加构造代码

}

Clesson6MFCMDIView::~Clesson6MFCMDIView()
{
}

BOOL Clesson6MFCMDIView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: 在此处通过修改
	//  CREATESTRUCT cs 来修改窗口类或样式

	return CView::PreCreateWindow(cs);
}

// Clesson6MFCMDIView 绘制

void Clesson6MFCMDIView::OnDraw(CDC* /*pDC*/)
{
	Clesson6MFCMDIDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: 在此处为本机数据添加绘制代码
    glClearColor(1,0,0,1);
	glClear(GL_COLOR_BUFFER_BIT);
	_context.swapBuffer();
}


// Clesson6MFCMDIView 打印

BOOL Clesson6MFCMDIView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// 默认准备
	return DoPreparePrinting(pInfo);
}

void Clesson6MFCMDIView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加额外的打印前进行的初始化过程
}

void Clesson6MFCMDIView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: 添加打印后进行的清理过程
}


// Clesson6MFCMDIView 诊断

#ifdef _DEBUG
void Clesson6MFCMDIView::AssertValid() const
{
	CView::AssertValid();
}

void Clesson6MFCMDIView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

Clesson6MFCMDIDoc* Clesson6MFCMDIView::GetDocument() const // 非调试版本是内联的
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(Clesson6MFCMDIDoc)));
	return (Clesson6MFCMDIDoc*)m_pDocument;
}
#endif //_DEBUG


// Clesson6MFCMDIView 消息处理程序

void Clesson6MFCMDIView::OnInitialUpdate()
{
	CView::OnInitialUpdate();

	// TODO: 在此添加专用代码和/或调用基类
    HDC  hDC  =  ::GetDC(m_hWnd);
	_context.setup(m_hWnd,hDC);
}

void Clesson6MFCMDIView::OnDestroy()
{
	_context.shutdown();
	CView::OnDestroy();

	// TODO: 在此处添加消息处理程序代码
}

BOOL Clesson6MFCMDIView::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
    return TRUE;
	return CView::OnEraseBkgnd(pDC);
}
  • 运行结果:
error












11月12日

总结:
::访问全局函数,否则访问的是类成员函数
MFC常用函数:OnCreate和OnInitialUpDate;(重写里)
OnCreate:产生VIEW的基本结构和变量;
OnInitialUpDate:主要初始化视图中控件等,对各个变量进行初始化操作;
(消息里)
OnDestroy():
void Clesson6testView::OnDestroy()
{
	_context.shutdown();
	CView::OnDestroy();
}
OnDraw():
void Clesson6testView::OnDraw(CDC* /*pDC*/)
{
	Clesson6testDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

    glClearColor(1,0,0,1);
	glClear(GL_COLOR_BUFFER_BIT);
    _context.swapBuffer();
}
  • 昨天造成error的原因:

OpenGL绑定的时候,RC跟DC绑定;当创建对象时,就与当前DC绑定,上一个DC改变,也就是失效了

  • 解决:

在GLContext.h中: bool makeCurrent() { if(!wglMakeCurrent(_hDC,_hRC)) { return false; } else { return true; }

}

  • 正确运行:
正确运行












  • 会有一定的性能损失,因为在一个线程里创建的多个窗口(调用makeCurrent()时性能损耗)

11月13日

  • win32下搭建OpenGL ES 2.0的开发环境
AMD的OpenGL ES2.0的模拟器和《OpenGL ES2.0 Programming guide》里的例子代码下载地址:
https://download.csdn.net/download/a1317338022/10140526?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160526472019724838502568%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=160526472019724838502568&biz_id=1&utm_medium=distribute.pc_search_result.none-task-download-2~all~first_rank_v2~rank_v28-1-10140526.pc_search_result_cache&utm_term=OpenGL+ES2.0%E7%9A%84%E6%A8%A1%E6%8B%9F%E5%99%A8&spm=1018.2118.3001.4449
(1)安装AMD模拟器,将其类库导入到VS中以方便程序对类库的引用和编译。
在模拟器的安装目录下,找到bin目录下的文件libEGL.dll和libGLESv2.dll,以及lib目录下的libEGL.lib和libGLESv2.lib,将这四个文件都复制到VS下面的VC目录中的bin和lib文件目录下面。
(2)定位到OpenGL_ES_Programming_Guide_v1.0.2\Chapter_2\Hello_Triangle,并且用VS打开工程文件Hello_Triangle.sln
工程结构



















报错:

报错











  • 解决方案:

(1) 右键项目Hello_Triangle: 配置属性-链接器-常规,把输出文件改成:Debug\$(ProjectName).exe 输入-附加依赖项:esUtil_d.lib改成esUtil.lib 补充:生成.exe文件后,双击打开提示"...计算机中丢失xxx.dll...",解决方法是直接将关联到的.dll文件直接复制到.exe文件所在的目录之下。

  • 遇到问题:
报错











  • 解决方案:




总结:
OpenGL ES在windows下没没有一个现成的库,所以要用到第三方的库,OpenGL ES是OpenGL下的一个子集,在windows版里OpenGL ES用d3d进行封装,效率比OpenGL更高,远程访问,OpenGL ES可以做,而OpenGL不能做,用OpenGL ES更好
OpenGL ES和OpenGL区别:
OpenGL ES所有的函数、参数都是一致的;OpenGL函数、参数与操作系统相关
AMD\OpenGL ES 2.0 Emulator v1.4\include里是OpenGLES2.0的头文件
AMD\OpenGL ES 2.0 Emulator v1.4\lib里是OpenGLES2.0的库文件

11月14-15日

  • 使用课上源码的总结:
OpenGL\Dependencies\include\gles2里是OpenGL ES2.0的规范头文件
OpenGL\Dependencies\lib\win32或者x64里是OpenGL ES2.0的库文件
OpenGL\bin\debugWin32里的d3dcompiler_43.dll,libEGL.dll,libGLESv2.dll是运行时库,是在windows下实现的库
配置属性:
项目属性--配置属性--常规--输出目录:../../temp/$(ConfigurationName)/$(PlatformName)/$(ProjectName)
项目属性--配置属性--常规--中间目录:../../temp/$(ConfigurationName)/$(PlatformName)/$(ProjectName)
项目属性--C/C++ --常规--附加包含目录:../../Dependencies/include
项目属性--配置属性--链接器--输出文件:../../bin/$(ConfigurationName)$(PlatformName)/$(ProjectName).exe
项目属性--配置属性--链接器--附加库目录:../../Dependencies/lib/$(PlatformName)
#pragma once
//GLES环境下的初始化
#include "gles2/gl2.h"
#include "gles2/egl.h"
class   GLESContext
{
public:
    EGLConfig	        _config;
    EGLSurface          _surface;
    EGLContext          _context;
    EGLDisplay          _display;//上面4个是用到的EGL环境的初始化
    HWND                _hWnd;
    HDC                 _hDC;
    int                 _winWidth;
    int                 _winHeight;
public:
    GLESContext()
    {
        _config         =   0;
        _display        =   EGL_NO_DISPLAY;
        _context        =   EGL_NO_CONTEXT;
        _surface        =   EGL_NO_SURFACE;

        _hWnd           =   0;
        _hDC            =   0;
        _winWidth       =   0;
        _winHeight      =   0;
    }

    ~GLESContext()
    {
        shutdown();
    }
    /**
    *   初始化EGL
    */
    bool    setup(HWND hWnd,HDC hDC)//输入窗口句柄和DC
    {
        _hWnd   =   hWnd;
        _hDC    =   hDC;
        shutdown();//一次初始化可以不调用

        const EGLint attribs[] =  //声明一个属性列表
        {
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT, //创建的表面类型,用window来创建
            EGL_BLUE_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_RED_SIZE, 8,
            EGL_ALPHA_SIZE, 8,//各种颜色缓冲区占的bit位
            EGL_DEPTH_SIZE,16,//也可以创建24,,32
            EGL_NONE
        };
        EGLint 	format(0);
        EGLint	numConfigs(0);
        EGLint  major;
        EGLint  minor;
        _display	    =	eglGetDisplay(hDC); //根据DC得到一个显示设备

        eglInitialize(_display, &major, &minor); //初始化,返回值是两个版本号(一般情况1,4)

        eglChooseConfig(_display, attribs, &_config, 1, &numConfigs); //返回满足条件的attribs

        eglGetConfigAttrib(_display, _config, EGL_NATIVE_VISUAL_ID, &format); //根据上面信息得到format(格式码)

        _surface	    = 	eglCreateWindowSurface(_display, _config, hWnd, NULL); //创建表面,理解为图片
        if (_surface == 0)
        {
            return  false;
        }
//前面创建的ES,创建OpenGL ES环境
        EGLint attr[]   =   { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};//版本是2
        _context 	    = 	eglCreateContext(_display, _config, 0, attr);
        if (_context == 0)
        {
            eglDestroySurface(_display,_surface);
            eglTerminate(_display); //失败就销毁结束
            return  false;
        }

        if (eglMakeCurrent(_display, _surface, _surface, _context) == EGL_FALSE) //将_display,_surface,_context关联在一起,做成对象
        {
            eglDestroySurface(_display,_surface);
            eglTerminate(_display);
            return false;
        }
        //修正窗口的宽高
        eglQuerySurface(_display, _surface, EGL_WIDTH,  &_winWidth); 
        eglQuerySurface(_display, _surface, EGL_HEIGHT, &_winHeight);

        return  true;
    }
    /**
    *   销毁EGL
    */
    void    shutdown()
    {
        if (_display != EGL_NO_DISPLAY)
        {
            eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
            if (_context != EGL_NO_CONTEXT) 
            {
                eglDestroyContext(_display, _context);
            }
            if (_surface != EGL_NO_SURFACE) 
            {
                eglDestroySurface(_display, _surface);
            }
            eglTerminate(_display);
        }
        _display    =   EGL_NO_DISPLAY;
        _context    =   EGL_NO_CONTEXT;
        _surface    =   EGL_NO_SURFACE;
    }
    /**
    *   交换缓冲区
    */
    void    swapBuffer()
    {
        eglSwapBuffers(_display,_surface);
    }
};
  • 报错:
报错







  • 解决:

项目属性--配置属性--链接器--输入--附加依赖项--OpenGL32.lib

  • 运行:
运行














11月16日

  • MFC-对话框下建立OpenGLES2.0环境
属性配置:
项目属性--常规--输出目录:../../temp/$(ConfigurationName)/$(PlatformName)/$(ProjectName)
中间目录:../../temp/$(ConfigurationName)/$(PlatformName)/$(ProjectName)
C/C++ --附加包含目录:../../include
链接器--常规--输出文件:../../bin/$(ConfigurationName)$(PlatformName)/$(ProjectName).exe
链接器--常规--附加库目录:../../lib/$(PlatformName)
链接器--输入--附加依赖项:libEGL.lib libGLESv2.lib
  • 编译运行:
编译运行










// lesson8-MFC-Dialog-ES2Dlg.cpp : 实现文件
//

#include "stdafx.h"
#include "lesson8-MFC-Dialog-ES2.h"
#include "lesson8-MFC-Dialog-ES2Dlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// Clesson8MFCDialogES2Dlg 对话框




Clesson8MFCDialogES2Dlg::Clesson8MFCDialogES2Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(Clesson8MFCDialogES2Dlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void Clesson8MFCDialogES2Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(Clesson8MFCDialogES2Dlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_WM_DESTROY()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()


// Clesson8MFCDialogES2Dlg 消息处理程序

BOOL Clesson8MFCDialogES2Dlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	//如果GetDC()->GetSafeHdc(),返回值是指针,建议下面写法
	_context.setup(m_hWnd,::GetDC(m_hWnd));

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void Clesson8MFCDialogES2Dlg::OnPaint()
{
	glClearColor(1,0,0,1);
	glClear(GL_COLOR_BUFFER_BIT);
	_context.swapBuffer();
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR Clesson8MFCDialogES2Dlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}
void Clesson8MFCDialogES2Dlg::OnDestroy()
{
    _context.shutdown();
	CDialog::OnDestroy();

	// TODO: 在此处添加消息处理程序代码
}

BOOL Clesson8MFCDialogES2Dlg::OnEraseBkgnd(CDC* pDC)
{
	return true;
}
  • 运行结果:
运行














11月17日

  • 全屏窗口(OpenGL)
//代码基于lesson7
#include <windows.h>
#include <tchar.h>
#include "GLESContext.h"

LRESULT CALLBACK  wndProc(HWND hWnd, UINT msgId, WPARAM wParam, LPARAM lParam)
{
    switch(msgId)
    {
    case WM_CLOSE:
    case WM_DESTROY:
        {
            PostQuitMessage(0);
        }
        break;
    default:
        return DefWindowProc(hWnd, msgId, wParam, lParam);
    }
    return  0;

}
void  ChangeToFullScreen(int w,int h)//给出宽高
{
	DEVMODE dmSettings = {0}; //声明一个针对屏幕显示器的设置

	if(!EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dmSettings)) //枚举下是否支持当前setting
	{
		MessageBox(NULL,_T("Could Not Enum Display Settings"),_T("Error"),MB_OK);
		return;
	}
  
	dmSettings.dmPelsWidth  = w;
    dmSettings.dmPelsHeight = h;
    dmSettings.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT ; //告诉改变高度宽度像素
	
	int result = ChangeDisplaySettings(&dmSettings,CDS_FULLSCREEN); //改变当前显示器的设置——全屏

	if(result != DISP_CHANGE_SUCCESSFUL)
	{
		MessageBox(NULL,_T("Display Mode Not Compatible"),_T("Error"),MB_OK);
		PostQuitMessage(0);
	}

}

int __stdcall WinMain( 
                      HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, 
                      int nShowCmd
                      )
{
    //1 注册窗口类
    WNDCLASSEX  wnd;

    memset(&wnd,0,sizeof(wnd));

    wnd.cbSize          =   sizeof(wnd);
    wnd.lpfnWndProc     =   wndProc;
    wnd.hbrBackground   =   (HBRUSH)GetStockObject(GRAY_BRUSH);
    wnd.hCursor         =   LoadCursor(hInstance,IDC_ARROW);
    wnd.hIcon           =   0;
    wnd.hIconSm         =   0;
    wnd.hInstance       =   hInstance;
    wnd.lpszClassName   =   _T("lesson01");
    wnd.style           =   CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

    RegisterClassEx(&wnd);

    //2 创建窗口
    HWND hWnd   =   CreateWindowEx(
        0
        , _T("lesson01") 
        , _T("窗口标题") 
        , WS_POPUP | WS_VISIBLE //没有了标题栏,是整个窗口;可见
        , 100
        , 100
        , 480
        , 320
        , 0
        , 0
        ,hInstance
        , 0);
	ChangeToFullScreen(800,600);

    //!3    更新显示
    if (hWnd)
    {
        UpdateWindow(hWnd);
        ShowWindow(hWnd,SW_SHOW);
    }

    else
    {
        return  0;
    }

    GLESContext   context;

    if (!context.setup(hWnd,GetDC(hWnd)))
    {
        return  0;
    }
   
    MSG     msg =   {0};

    //4 消息循环
    while(WM_QUIT != msg.message) 
    {

        if(PeekMessage(&msg, 0, 0, 0,PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        } 
        else
        {
            /**
            *   调用绘制函数进行绘制
            */
            glClearColor(1,0,0,1);
            glClear(GL_COLOR_BUFFER_BIT);
            context.swapBuffer();

        }
    }
    context.shutdown();
    return  0;
}
  • 运行结果:
全屏运行















11月18日

  • 在window下glut环境的建立
glut是一个简单的库,对OpenGL环境的初始化进行了封装
  • 步骤:

1、将glut.dll,glut.h,glut.lib,glut32.dll,glut32.lib拷贝到项目文件下 2、项目属性--配置属性--链接器--输入--附加依赖项:glut32.lib

//lesson10.cpp

#include "glut.h"

void display(void)
{
	glClearColor(1,0,0,1);
	glClear(GL_COLOR_BUFFER_BIT);
	glFlush();
        glutSwapBuffers();
}

int main(int argc,char* argv[])
{
	glutInit(&argc,argv);
	glutInitWindowPosition(10,10);
	glutInitWindowSize(400,600);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); //窗口显示模式,第一个也可为GLUT_DOUBLE
	glutCreateWindow("lesson10");

	glutDisplayFunc(display); //函数回调
	glutMainLoop(); //相当消息循环

	return 0;
}
  • 运行:
运行














  • glfw框架的搭建
glfw是一个开源的、跨平台的的库,灵活性比glut高
  • 步骤:

1、将glfw3.h,glfw3native.h拷贝到项目文件下 2、项目属性--配置属性--链接器--输入--附加依赖项:glfw3dll.lib opengl32.lib

//lesson11.cpp
#include "GLFW/glfw3.h"
#include <stdlib.h>
#include <stdio.h>

static void error_callback(int error,const char* description)
{
	fprintf(stderr,"Error:%s\n",description);
}
static void key_callback(GLFWwindow* window,int key,int scancode,int action,int mods)
{
	if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
		glfwSetWindowShouldClose(window,GLFW_TRUE);
}
int main(int argc,char** argv)
{
	GLFWwindow* window; //声明窗口对象
	

	glfwSetErrorCallback(error_callback);

	if(!glfwInit())
		exit(EXIT_FAILURE);
    //设置版本号
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,2);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,0);
   //创建一个窗口
	window = glfwCreateWindow(640,400,"Simple example",NULL,NULL);
	if(!window)
	{
		glfwTerminate();
		exit(EXIT_FAILURE);
	}

	glfwSetKeyCallback(window,key_callback);//设置键盘的回调;可设可不设

	glfwMakeContextCurrent(window);
	glfwSwapInterval(1);
    //类似于消息回调
    while(!glfwWindowShouldClose(window))//如果窗口没有被关闭,执行以下
	{
		glClearColor(0,1,1,1);

		glClear(GL_COLOR_BUFFER_BIT);

		glfwSwapBuffers(window);
		glfwPollEvents(); //获取窗口事件,是否有键盘按下,是否有鼠标按下
	}

	glfwDestroyWindow(window);

	glfwTerminate();
}
  • 报错:

c:\users\dell\documents\visual studio 2008\projects\lesson11-glfw-window\lesson11-glfw-window\glfw\glfw3.h(108) : fatal error C1083: 无法打开包括文件:“stdint.h”: No such file or directory

  • 解决:
更改头文件








  • 运行:
运行











11月19日

  • QT下建立OpenGL环境
1、下载VS2008编译好的QT4.7版本:qt-win-opensource-4.7.4-vs2008.exe
2、下载VS2008的Qt插件:qt-vs-addin-1.1.9.exe
3、配置属性:
项目属性--常规--输出目录:../../temp/$(ConfigurationName)/$(PlatformName)/$(ProjectName)
中间目录:../../temp/$(ConfigurationName)/$(PlatformName)/$(ProjectName)
链接器--输出文件:../../bin/$(ConfigurationName)$(PlatformName)/$(ProjectName).exe
链接器--输入--附加依赖项--Debug:添加OpenGL32.lib
4、将GLContext.h添加到项目目录里来
//myclass.cpp
#include "myclass.h"

MyClass::MyClass(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{
	ui.setupUi(this);

	_context.setup(winId(),getDC()); //创建;只是绘制了一次
	QObject::connect(&_renderTimer,SIGNAL(timeout()),this,SLOT(render()));
    _renderTimer.setInterval(16);//每16毫秒更新一下
	_renderTimer.start();
}

MyClass::~MyClass()
{
    _context.shutdown();
}

void MyClass::paintEvent( QPaintEvent* evt)
{

}
void MyClass::render()
{
	glClearColor(1,0,0,1);
	glClear(GL_COLOR_BUFFER_BIT);
	_context.swapBuffer();
}
//myclass.h

#ifndef MYCLASS_H
#define MYCLASS_H

#include <QtGui/QMainWindow>
#include <QTimer>
#include "ui_myclass.h"

#include "GLContext.h"

class MyClass : public QMainWindow
{
	Q_OBJECT

public:
	MyClass(QWidget *parent = 0, Qt::WFlags flags = 0);
	~MyClass();

	GLContext _context;
    QTimer    _renderTimer;
public Q_SLOTS:

	void render();

protected:
	void paintEvent(QPaintEvent* evt);
	
private:
	Ui::MyClassClass ui;
};

#endif // MYCLASS_H
  • 运行:
运行















  • QT下建立OpenGLES2.0环境
1、将GLESContext.h添加到项目目录里来
2、修改配置属性,同上;不同之处:
3、链接器--输入--附加依赖项--输入--活动(Debug):添加libEGL.lib,libGLESv2.lib
4、C/C++ --常规--附加包含目录:../../include
5、链接器--常规--附加库目录:../../lib/$(PlatformName)
//qopengles2widget.h
#ifndef QOPENGLES2WIDGET_H
#define QOPENGLES2WIDGET_H

#include <QWidget>
#include <QTimer>
#include "ui_qopengles2widget.h"

#include "GLESContext.h"

class QOpenGLES2Widget : public QWidget
{
	Q_OBJECT

public:
	QOpenGLES2Widget(QWidget *parent = 0);
	~QOpenGLES2Widget();

public Q_SLOTS:
	void render();

protected:
	QTimer      _timer;
	GLESContext _content;
private:
	Ui::QOpenGLES2Widget ui;
};
#endif // QOPENGLES2WIDGET_H
//myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H

#include <QtGui/QMainWindow>
#include "ui_myclass.h"

#include "qopengles2widget.h"

class MyClass : public QMainWindow
{
	Q_OBJECT

public:
	QOpenGLES2Widget* gles;

public:
	MyClass(QWidget *parent = 0, Qt::WFlags flags = 0);
	~MyClass();

private:
	Ui::MyClassClass ui;
};
#endif // MYCLASS_H
#include "myclass.h"
//在此调用窗口
MyClass::MyClass(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{
	ui.setupUi(this);
	gles = new QOpenGLES2Widget(); 
}

MyClass::~MyClass()
{

}
  • 运行:
运行




















  • 子窗口运行:

改动:myclass.cpp里:gles = new QOpenGLES2Widget(this); //做成子窗口

子窗口运行

















#include "myclass.h"

#include <QHBoxLayout>
//在此调用窗口
MyClass::MyClass(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{
	ui.setupUi(this);
	gles = new QOpenGLES2Widget(this); //做成子窗口

	gles->resize(400,400); //改变窗口大小
	gles->show();

	QWidget* center  =  centralWidget();
	QHBoxLayout* layout =  new QHBoxLayout(center); //水平布局
	layout->addWidget(gles);//添加控件 默认的,添加控件至水平布局中,默认都是垂直方向居中对齐的

}

MyClass::~MyClass()
{

}
  • 报错:
报错














  • 解决:
#include "myclass.h"

#include <QHBoxLayout>
//在此调用窗口
MyClass::MyClass(QWidget *parent, Qt::WFlags flags)
	: QMainWindow(parent, flags)
{
	ui.setupUi(this);
	gles = new QOpenGLES2Widget(this); //做成子窗口

	gles->resize(400,400); //改变窗口大小
	gles->show();

	QWidget* center  =  centralWidget();
	QHBoxLayout* layout =  new QHBoxLayout(center); //水平布局
	layout->addWidget(gles);//添加控件 默认的,添加控件至水平布局中,默认都是垂直方向居中对齐的

	gles->setup();
}

MyClass::~MyClass()
{

}
#include "qopengles2widget.h"

QOpenGLES2Widget::QOpenGLES2Widget(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
//	_content.setup(winId(),getDC());//不能直接建立openGL环境,需要在.h里单独加函数

	QObject::connect(&_timer,SIGNAL(timeout()),this,SLOT(render()));//信号和槽连接起来
    _timer.setInterval(16);
	_timer.start();
}

QOpenGLES2Widget::~QOpenGLES2Widget()
{
     _content.shutdown();
}

void QOpenGLES2Widget::render()
{
	glClearColor(0,0,1,1);
	glClear(GL_COLOR_BUFFER_BIT);
	_content.swapBuffer();
}

void QOpenGLES2Widget::setup()
{
	_content.setup(winId(),getDC());
}
//qopengles2widget.h
#ifndef QOPENGLES2WIDGET_H
#define QOPENGLES2WIDGET_H

#include <QWidget>
#include <QTimer>
#include "ui_qopengles2widget.h"

#include "GLESContext.h"

class QOpenGLES2Widget : public QWidget
{
	Q_OBJECT

public:
	QOpenGLES2Widget(QWidget *parent = 0);
	~QOpenGLES2Widget();

	void setup();

public Q_SLOTS:
	void render();

protected:
	QTimer      _timer;
	GLESContext _content;
private:
	Ui::QOpenGLES2Widget ui;
};

#endif // QOPENGLES2WIDGET_H
  • 运行:
正确运行















11月20--22日

  • 安卓下纯C++(NDK)进行OpenGLES开发(不通过JNI)
1、安卓的操作系统底层是用纯C、C++实现的
2、安卓提供了两种方案来开发C++,①通过JNI/JNA(JNA比JNI简单)开发②利用NDK开发(纯C++编写的程序)
  • 搭建安卓开发环境:
①下载java的开发环境:jdk;配置环境变量
②下载 Andriod SDK;配置环境变量
③下载 Andriod NDK
④下载apache-ant-1.9.2;配置环境变量
⑤安装.bluestacks模拟器
总结:
报错:将NativeActivity导入Eclipse后,gen里BuildConfig.java出错
解决:把java的类库加载进去,在工程上右键选择属性->Java Build Path的Libraries->Add Library选择JRE System Library->点击Next->选择Execution environment并选择jre版本或workspace default jre(有显示的版本不是都能选的的,只有默认自带的jre和安装绑定过的选了才能起作用)->点击Finish。
报错:Unable to resolve target 'android-20'
解决:①修改project.properties里的target,但Eclipse仍然会报这种错误
      ②不要用import project, 而是用New ->Android Project 中的Create project from existing source。这样在导入的时候可以选择target(也就是SDK的版本)。
//main.h
#include <errno.h>

#include <EGL/egl.h>
#include <GLES/gl.h>

#include <android/sensor.h>
#include <android/log.h>
#include <android_native_app_glue.h>

#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))

/**
 * Our saved state data.
 */
struct saved_state
{
    float angle;
    int32_t x;
    int32_t y;
};

/**
 * Shared state for our app.
 */
struct engine
{
    struct android_app* app;

    ASensorManager* 	sensorManager;
    const ASensor* 		accelerometerSensor;
    ASensorEventQueue* 	sensorEventQueue;

    int 		animating;
    EGLDisplay 	display;
    EGLSurface 	surface;
    EGLContext 	context;
    int32_t 	width;
    int32_t 	height;
    struct saved_state state;
};

/**
 * Initialize an EGL context for the current display.
 */
static int engine_init_display(struct engine* engine)
{
    // initialize OpenGL ES and EGL
    const EGLint attribs[] =
    {
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
            EGL_BLUE_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_RED_SIZE, 8,
            EGL_NONE
    };
    EGLint w, h, dummy, format;
    EGLint 		numConfigs;
    EGLConfig 	config;
    EGLSurface 	surface;
    EGLContext 	context;

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    eglInitialize(display, 0, 0);

    /* Here, the application chooses the configuration it desires. In this
     * sample, we have a very simplified selection process, where we pick
     * the first EGLConfig that matches our criteria */
    eglChooseConfig(display, attribs, &config, 1, &numConfigs);

    /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
     * guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
     * As soon as we picked a EGLConfig, we can safely reconfigure the
     * ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); //新增的;告诉安装创建的窗口的格式

    ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);

    surface	= 	eglCreateWindowSurface(display, config, engine->app->window, NULL);
    context	= 	eglCreateContext(display, config, NULL, NULL);

    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
    {
        LOGW("Unable to eglMakeCurrent");
        return -1;
    }

    eglQuerySurface(display, surface, EGL_WIDTH, &w);
    eglQuerySurface(display, surface, EGL_HEIGHT, &h);

    engine->display 	= 	display;
    engine->context 	= 	context;
    engine->surface 	= 	surface;
    engine->width 		=	w;
    engine->height 		= 	h;
    engine->state.angle = 	0;

    return 0;
}

/**
 * Just the current frame in the display.
 */
static void engine_draw_frame(struct engine* engine)
{
    if (engine->display == NULL)
    {
        return;
    }

    // Just fill the screen with a color.
    glClearColor(
    		  (float)engine->state.x/(float)engine->width
    		, engine->state.angle
    		, (float)engine->state.y/(float)engine->height
    		, 1);
    glClear(GL_COLOR_BUFFER_BIT);

    eglSwapBuffers(engine->display, engine->surface);
}

/**
 * Tear down the EGL context currently associated with the display.
 */
static void engine_term_display(struct engine* engine)
{
    if (engine->display != EGL_NO_DISPLAY)
    {
        eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
        if (engine->context != EGL_NO_CONTEXT)
        {
            eglDestroyContext(engine->display, engine->context);
        }
        if (engine->surface != EGL_NO_SURFACE)
        {
            eglDestroySurface(engine->display, engine->surface);
        }
        eglTerminate(engine->display);
    }
    engine->animating 	= 	0;
    engine->display 	= 	EGL_NO_DISPLAY;
    engine->context 	= 	EGL_NO_CONTEXT;
    engine->surface 	= 	EGL_NO_SURFACE;
}

/**
 * Process the next input event.
 */
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
{
    struct engine* engine = (struct engine*)app->userData;
    if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION)
    {
        engine->animating 	= 	1;
        engine->state.x 	= 	AMotionEvent_getX(event, 0);
        engine->state.y 	= 	AMotionEvent_getY(event, 0);
        return 1;
    }
    return 0;
}

/**
 * Process the next main command.
 */
static void engine_handle_cmd(struct android_app* app, int32_t cmd) //Android消息处理函数
{
    struct engine* engine = (struct engine*)app->userData;
    switch (cmd)
    {
        case APP_CMD_SAVE_STATE:
            // The system has asked us to save our current state.  Do so.
            engine->app->savedState = malloc(sizeof(struct saved_state));
            *((struct saved_state*)engine->app->savedState) = engine->state;
            engine->app->savedStateSize = sizeof(struct saved_state);
            break;
        case APP_CMD_INIT_WINDOW:
            // The window is being shown, get it ready.
            if (engine->app->window != NULL)
            {
                engine_init_display(engine);
                engine_draw_frame(engine);
            }
            break;
        case APP_CMD_TERM_WINDOW:
            // The window is being hidden or closed, clean it up.
            engine_term_display(engine);
            break;
        case APP_CMD_GAINED_FOCUS:
            // When our app gains focus, we start monitoring the accelerometer.
            if (engine->accelerometerSensor != NULL)
            {
                ASensorEventQueue_enableSensor(engine->sensorEventQueue,engine->accelerometerSensor);
                // We'd like to get 60 events per second (in us).
                ASensorEventQueue_setEventRate(engine->sensorEventQueue,engine->accelerometerSensor, (1000L/60)*1000);
            }
            break;
        case APP_CMD_LOST_FOCUS:
            // When our app loses focus, we stop monitoring the accelerometer.
            // This is to avoid consuming battery while not being used.
            if (engine->accelerometerSensor != NULL)
            {
                ASensorEventQueue_disableSensor(engine->sensorEventQueue,engine->accelerometerSensor);
            }
            // Also stop animating.
            engine->animating = 0;
            engine_draw_frame(engine);
            break;
    	}
}

/**
 * This is the main entry point of a native application that is using
 * android_native_app_glue.  It runs in its own thread, with its own
 * event loop for receiving input events and doing other things.
 */
void android_main(struct android_app* state) //开始
{
    struct engine engine;

    // Make sure glue isn't stripped.
    app_dummy();//此函数在#include <android_native_app_glue.h>里;保证库不会被优化掉

    memset(&engine, 0, sizeof(engine));
    state->userData		= 	&engine;
    state->onAppCmd 	= 	engine_handle_cmd;
    state->onInputEvent = 	engine_handle_input;
    engine.app 			= 	state;

    engine.sensorManager 		= 	ASensorManager_getInstance();
    engine.accelerometerSensor 	= 	ASensorManager_getDefaultSensor(engine.sensorManager,ASENSOR_TYPE_ACCELEROMETER);
    engine.sensorEventQueue 	= 	ASensorManager_createEventQueue(engine.sensorManager,state->looper, LOOPER_ID_USER, NULL, NULL);

    if (state->savedState != NULL)
    {
        // We are starting with a previous saved state; restore from it.
        engine.state = *(struct saved_state*)state->savedState;
    }

    // loop waiting for stuff to do.

    while (1)
    {
        // Read all pending events.
        int ident;
        int events;
        struct android_poll_source* source;

        // If not animating, we will block forever waiting for events.
        // If animating, we loop until all events are read, then continue
        // to draw the next frame of animation.
        while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, NULL, &events,
                (void**)&source)) >= 0)
        {

            // Process this event.
            if (source != NULL)
            {
                source->process(state, source);
            }

            // If a sensor has data, process it now.
            if (ident == LOOPER_ID_USER)
            {
                if (engine.accelerometerSensor != NULL)
                {
                    ASensorEvent event;
                    while (ASensorEventQueue_getEvents(engine.sensorEventQueue,
                            &event, 1) > 0)
                    {
                        LOGI("accelerometer: x=%f y=%f z=%f",
                                event.acceleration.x, event.acceleration.y,
                                event.acceleration.z);
                    }
                }
            }

            // Check if we are exiting.
            if (state->destroyRequested != 0)
            {
                engine_term_display(&engine);
                return;
            }
        }

        if (engine.animating)
        {
            engine.state.angle += .01f;
            if (engine.state.angle > 1)
            {
                engine.state.angle = 0;
            }

            engine_draw_frame(&engine);
        }
    }
}
//END_INCLUDE(all)

11月23日

  • 新建一个Android Project
1、新建一个Android Application Project
2、将现有项目中jni的main.c、Android.mk、Application.mk拷贝到新建的项目jni中
3、修改AndroidManifest.xml
# Copyright (C) 2010 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := test001
LOCAL_SRC_FILES := test001.cpp

LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM 
LOCAL_STATIC_LIBRARIES := android_native_app_glue

include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/native_app_glue)
<?xml version="1.0" encoding="utf-8"?>
<!-- AndroidManifest.xml -->
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.native_activity"
        android:versionCode="1"
        android:versionName="1.0">

    <!-- This is the platform API where NativeActivity was introduced. -->
    <uses-sdk android:minSdkVersion="9" />

    <!-- This .apk has no Java code itself, so set hasCode to false. -->
    <application android:label="@string/app_name" android:hasCode="false">

        <!-- Our activity is the built-in NativeActivity framework class.
             This will take care of integrating with our NDK code. -->
<!--这句关键,名字必须以.NativeActivity结尾 -->
        <activity android:name="android.app.NativeActivity" 
                android:label="@string/app_name"
                android:configChanges="orientation|keyboardHidden">
            <!-- Tell NativeActivity the name of or .so -->
            <meta-data android:name="android.app.lib_name"
                    android:value="native-activity" />
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest> 
<!-- END_INCLUDE(manifest) -->
  • 报错:
  Can't find API database; API check was not performed
  • 解决:
  点击错误 problems中的带有红X的item选项——>quick fix——>选择Disable Check in This Project
  • 第二章:基础图元
  • OpenGL投影
OpenGL投影














  • 正交投影
正交投影
















正交没有远小近大的效果

正交投影














总结:
1、在当前窗口上建立一个新的坐标系,所有的绘制数据都建立在这个新的坐标系下,定义了如何将数据显示到窗口上的一个过程
2、优点:灵活;支持业务需要
   缺点:增加了额外的坐标转换计算
void glOrtho(
   GLdouble left,
   GLdouble right,
   GLdouble bottom,
   GLdouble top,
   GLdouble zNear,
   GLdouble zFar
)

11月24日

//代码基于lesson3-OpenGL
//lesson201.cpp
#include "GLContext.h"
//创建win32窗口

LRESULT CALLBACK wndProc(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
{
	switch(msgId)
	{
	case WM_CLOSE:
	case WM_DESTROY:
		{
			PostQuitMessage(0);
		}
		break;
	default:
		return DefWindowProc(hWnd,msgId,wParam,lParam);
	}
	return 0;
}

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	//1注册窗口类
	WNDCLASSEX wnd;

	memset(&wnd,0,sizeof(wnd));

	wnd.cbSize          =   sizeof(wnd); //指明当前结构体大小
	wnd.lpfnWndProc     =   wndProc; //函数指针,若有事件发生,则调此函数
	wnd.hbrBackground   =   (HBRUSH)GetStockObject(GRAY_BRUSH);
	wnd.hCursor         =   LoadCursor(hInstance,IDC_ARROW);//鼠标样式
	wnd.hIcon           =   0;
	wnd.hIconSm         =   0;
	wnd.hInstance       =   hInstance;
	wnd.lpszClassName   =   _T("lesson01"); 
	wnd.style           =   CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	
	int width  = 480;
	int height = 320;
	
	RegisterClassEx(&wnd);  //调用注册窗口类函数
	//2创建窗口
	HWND hWnd  =   CreateWindowEx(
		0 // 窗口的扩展风格
		,_T("lesson01")//需和wnd.lpszClassName一致
		,_T("lesson01")//窗口标题
		,WS_OVERLAPPEDWINDOW//窗口风格,有无最大化最小化
		,100//窗口在屏幕的位置
		,100//窗口在屏幕的位置
		,480//宽
		,320//高
		,0//系统菜单
		,0//父窗口
		,hInstance//实例句柄
		,0);//用户数据
	//3更新显示
	if(hWnd)
	{
		UpdateWindow(hWnd);
		ShowWindow(hWnd,SW_SHOW);
	}
	else
	{
		return 0;
	}

	GLContext context;
	if(!context.setup(hWnd,GetDC(hWnd)))
	{
		return 0;
	}
    
     RECT rect;
     GetClientRect(hWnd,&rect);

	 width  =  rect.right   - rect.left;
	 height =  rect.bottom  - rect.top;



	MSG  msg={0};
	//4消息循环
	while(WM_QUIT !=msg.message)
	{
		if(PeekMessage(&msg,0,0,0,PM_REMOVE))//有消息产生;点关闭按钮,返回值为false
		{
			TranslateMessage(&msg);//翻译
			DispatchMessage(&msg);//分发
		}
		else
		{
			/*调用绘制函数进行绘制*/
			glClearColor(1,0,1,1); //改变颜色
			glClear(GL_COLOR_BUFFER_BIT);//清空背景颜色

			glViewport(0,0,width,height);//指明OpenGL的视口;屏幕坐标,宽,高
			glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
			glLoadIdentity();//将投影矩阵清空成单位矩阵
			
			glOrtho(0,width,height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
		    
            glBegin(GL_LINES);

            glVertex3f(0,0,0);
            glVertex3f(100,100,0);

			glEnd();

			context.swapBuffer();
		}
	}
	context.shutdown();
	return 0;
}
  • 运行结果:
正交投影画线













总结:
1、给定模式是画线:
            glBegin(GL_LINES);

            glVertex3f(0,0,0);
            glVertex3f(100,100,0);

            glEnd();
2、画的线一闪而过
解决: glLoadIdentity();//将投影矩阵清空成单位矩阵;然后再glOrtho(0,width,height,0,-100,100);//产生投影矩阵;
3、画的线并不是从(0,0)位置开始的
解决:
         RECT rect;
         GetClientRect(hWnd,&rect);

	 width  =  rect.right   - rect.left;
	 height =  rect.bottom  - rect.top;
  • 绘制第一个三角形
  绘制之前要对现有的窗口进行面向对象的封装,可以更好地重用
1、拷贝lesson3的main.cpp和GLContext.h
2、新建OpenGLWindow.h

11月25日

  • 先完成对窗口的封装:
//OpenGLWindow.h
#pragma once
#include "GLContext.h"

class OpenGLWindow:public GLContext
{
protected:
	int _width;
	int _height;
public:
    OpenGLWindow(HINSTANCE hInst = 0)
	{
		//1注册窗口类
		WNDCLASSEX wnd;

		memset(&wnd,0,sizeof(wnd));

		wnd.cbSize          =   sizeof(wnd); //指明当前结构体大小
		wnd.lpfnWndProc     =   wndProc; //函数指针,若有事件发生,则调此函数
		wnd.hbrBackground   =   (HBRUSH)GetStockObject(GRAY_BRUSH);
		wnd.hCursor         =   LoadCursor(hInst,IDC_ARROW);//鼠标样式
		wnd.hIcon           =   0;
		wnd.hIconSm         =   0;
		wnd.hInstance       =   0;
		wnd.lpszClassName   =   _T("lesson201"); 
		wnd.style           =   CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
		RegisterClassEx(&wnd);  //调用注册窗口类函数


	}
    virtual	bool main(int w,int h)
	{
		//2创建窗口
	HWND	hWnd  =   CreateWindowEx(
			0 // 窗口的扩展风格
			,_T("lesson201")//需和wnd.lpszClassName一致
			,_T("lesson201")//窗口标题
			,WS_OVERLAPPEDWINDOW//窗口风格,有无最大化最小化
			,0//窗口在屏幕的位置
			,0//窗口在屏幕的位置
			,w//宽
			,h//高
			,0//系统菜单
			,0//父窗口
			,0//实例句柄
			,this);//用户数据,用户自定义 this指当前对象
		//3更新显示
		if(hWnd)
		{
			UpdateWindow(hWnd);
			ShowWindow(hWnd,SW_SHOW);
		}
		else
		{
			return false;
		}

		if(!setup(hWnd,GetDC(hWnd)))
		{
			return false;
		}


		MSG  msg={0};
		//4消息循环
		while(WM_QUIT !=msg.message)
		{
			if(PeekMessage(&msg,0,0,0,PM_REMOVE))//有消息产生;点关闭按钮,返回值为false
			{
				TranslateMessage(&msg);//翻译
				DispatchMessage(&msg);//分发
			}
			else
			{
				RECT rect;
				GetClientRect(hWnd,&rect);
				_width  =  rect.right  -  rect.left;
				_height =  rect.bottom -  rect.top;

				glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
				glViewport(0,0,_width,_height);

				render();
				swapBuffer();
			}
		}
		shutdown();

		return true;
	}

	virtual void render()
	{

	}
     /*消息处理过程*/
    virtual LRESULT events(UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_CLOSE:
		case WM_DESTROY:
			{
				PostQuitMessage(0);
			}
			break;
		default:
			return DefWindowProc(_hWnd,msgId,wParam,lParam);
		}
		return 0;
	}

protected:
	static LRESULT CALLBACK wndProc(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam) //lParam里 携带了this指针
	{
        if(msgId == WM_CREATE)
		{
           LPCREATESTRUCT  pData  =  (LPCREATESTRUCT)lParam;// LPCREATESTRUCT本身是指针
		   OpenGLWindow*   pTHis  =  (OpenGLWindow*)pData->lpCreateParams;
		   SetWindowLong(hWnd,GWL_USERDATA,(LONG)pTHis);//在当前窗口上关联了一个用户数据pTHis,window和变量关联放入GWL_USERDATA槽中
		   return DefWindowProc(hWnd,msgId,wParam,lParam);
		}
		else
		{
           OpenGLWindow*   pTHis  =  (OpenGLWindow*)GetWindowLong(hWnd,GWL_USERDATA);
		   if(pTHis)
		   {
            return pTHis->events(msgId,wParam,lParam);
		   }
		   else
		   {
            return DefWindowProc(hWnd,msgId,wParam,lParam); //调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理;该函数确保每一个消息得到处理
		   }
		      
		}
	}
};
  • 运行结果:
窗口封装完成














  • 接着绘制三角形
//添加到lesson002.cpp中
class SamplerTriangle:public OpenGLWindow
{
public:
    //在此实现绘制
	virtual void render()
	{
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射

        glColor3f(1,1,1);
		glBegin(GL_TRIANGLES);

		glVertex3f(_width * 0.5f,0,0);
		glVertex3f(_width,_height,0);
		glVertex3f(0,_height,0);

		glEnd();
	}
};
  • 运行:
绘制三角形
















11月26日

  • 三角形列表绘制圆(GL_TRIANGLE_LIST)
OpenGL里支持的多种绘制形状:
/* BeginMode */
#define GL_POINTS                         0x0000
#define GL_LINES                          0x0001 //两点画的线
#define GL_LINE_LOOP                      0x0002 //给三个点,第三点和第一点重合形成闭合区域
#define GL_LINE_STRIP                     0x0003 //三个点绘制两条线,四个点绘制三条线
#define GL_TRIANGLES                      0x0004 //三个点画一个扇形
#define GL_TRIANGLE_STRIP                 0x0005 //三个点形成一个三角形,再给定一个点,与最近两点再形成一个三角形
#define GL_TRIANGLE_FAN                   0x0006
绘制圆思路:
圆心+圆上一点+下一点组成三角形
圆上一点:
           float  x = (float)cos((double)i * M_PI/180)+ cx; //x:弧度
           float  y = (float)cos((double)i * M_PI/180)+ cy;
//lesson203.cpp
#include "OpenGLWindow.h"
#include <math.h>
//创建win32窗口

class SamplerTriangle:public OpenGLWindow
{
public:
	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射

        float cx=100;
		float cy=100;
		float cz=0;
		float r=80;
glBegin(GL_TRIANGLES);
		for(int i=0;i<360;++i)
		{
            float  x = r* (float)cos((double)i * M_PI/180)+ cx; //x:弧度
		    float  y = r* (float)sin((double)i * M_PI/180)+ cy;

			float  x1 = r* (float)cos((double)(i+1) * M_PI/180)+ cx; //x:弧度
			float  y1 = r* (float)sin((double)(i+1) * M_PI/180)+ cy;
		    
			glVertex3f(cx,cy,cz);//中心点
			glVertex3f(x,y,cz);
			glVertex3f(x1,y1,0);	
		}
		glEnd();
		glColor3f(1,1,1);
	}
};
//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTriangle instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
绘制圆
















  • 三角形列表绘-顶点数据方式绘制
更高效的绘制方式:
先准备好数据,然后将数据指针传给OpenGL
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>
//创建win32窗口

class SamplerTriangle:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct float3
	{
       float x,y,z;//3个顶点
	   float w;
	};
	float3 _circle[360 *3];

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射

        float cx=100;
		float cy=100;
		float cz=0;
		float r=80;
		for(int i=0;i<360;++i)
		{ 
            //中心点
            _circle[i * 3 + 0].x = cx;
            _circle[i * 3 + 0].y = cy;
			_circle[i * 3 + 0].z = cz;
            //圆上第一点
			_circle[i * 3 + 1].x = r * (float)cos((double)i * M_PI/180)+ cx;
			_circle[i * 3 + 1].y = r * (float)sin((double)i * M_PI/180)+ cy;
			_circle[i * 3 + 1].z = r * cz;
            //圆上第二点
			_circle[i * 3 + 2].x = r * (float)cos((double)(i+1) * M_PI/180)+ cx;
			_circle[i * 3 + 2].y = r * (float)sin((double)(i+1) * M_PI/180)+ cy;
			_circle[i * 3 + 2].z = r * cz;

		}
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),_circle); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glDrawArrays(GL_TRIANGLES,0,360 * 3);//从0开始,共360*3个点
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTriangle instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
更高效绘制圆
















  • 使用三角形扇绘制一个圆(GL_TRIANGLE_FAN)
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>
//创建win32窗口

class SamplerTriangle:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct float3
	{
       float x,y,z;//3个顶点
	   float w;
	};
	float3 _circle[362];

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射

        float cx=100;
		float cy=100;
		float cz=0;
		float r=80;
        glColor3f(1,1,1);
        //圆心
		_circle[0].x = cx;
		_circle[0].y = cy;
		_circle[0].z = cz;
        //生成数据
		for(int i = 0; i < 361; ++i)
		{ 
            //圆上第一点
			_circle[i + 1].x = r * (float)cos((double)i * M_PI/180)+ cx;
			_circle[i + 1].y = r * (float)sin((double)i * M_PI/180)+ cy;
			_circle[i + 1].z = r * cz;
		}
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),_circle); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glDrawArrays(GL_TRIANGLE_FAN,0,362);//从0开始,共360*3个点
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTriangle instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
GL TRIANGLE FAN画圆
















11月28日

  • 三角形带的使用(GL_TRIANGLE_STRIP)
GL_TRIANGLE_STRIP给定n个点,可以画出(n-2)个三角形
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>
//创建win32窗口

class SamplerTriangle:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct float3
	{
       float x,y,z;//3个顶点
	   float w;
	};
	float3 _circle[362];

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        glColor3f(1,1,1);
      
        float3 rect[] = 
		{
			{10,  10,   0},
			{110, 10,   0},
			{10,  110,  0},
			{110, 110,  0}
		};
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),rect); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glDrawArrays(GL_TRIANGLE_STRIP,0,4);//从0开始,共360*3个点
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTriangle instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
GL TRIANGLE STRIP画矩形
















  • 带颜色的三角形绘制
glColor3f(1,1,1)指定颜色是全局的,对所有顶点都生效;
(glEnableClientState(GL_COLOR_ARRAY);//启用颜色数组;
  glColorPointer(3,GL_FLOAT,sizeof(Vertex),&rect[0].r);可以对特定顶点指定颜色)
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>
//创建win32窗口

class SamplerTriangle:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct Vertex
	{
       float x,y,z;//3个顶点
	   float r,g,b;
	};

	//在此实现绘制
	virtual void render()
	{
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        
      
        Vertex rect[] = 
		{
			{10,  10,   0, 1, 0, 0},
			{110, 10,   0, 0, 1, 0},
			{10,  110,  0, 0, 0, 1},
			{110, 110,  0, 1, 0, 1}
		};
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);//启用颜色数组
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),rect); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glColorPointer(3,GL_FLOAT,sizeof(Vertex),&rect[0].r);
		glDrawArrays(GL_TRIANGLE_STRIP,0,4);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTriangle instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
带颜色的三角形绘制
















  • 线的绘制
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>
//创建win32窗口

class SamplerLane:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct Vertex
	{
       float x,y,z;//3个顶点
	   float r,g,b;
	};

	//在此实现绘制
	virtual void render()
	{
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        
      
        Vertex rect[] = 
		{
			{10,  10,   0, 1, 0, 0},
			{110, 10,   0, 0, 1, 0},
			{10,  110,  0, 0, 0, 1},
			{110, 110,  0, 1, 0, 1}
		};
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);//启用颜色数组
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),rect); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glColorPointer(3,GL_FLOAT,sizeof(Vertex),&rect[0].r);
		glDrawArrays(GL_LINE_STRIP,0,4);//4个点画三条线(线带)
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerLane instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
GL LINE STRIP画线
glDrawArrays(GL_LINES,0,4); //四个点画两条线(线段)
  • 运行:
GL LINES画线
glDrawArrays(GL_LINE_LOOP,0,4);//起点与终点闭合(闭合)
  • 运行:
GL LINE LOOP画线
















  • 更复杂的画线
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>
//创建win32窗口

class SamplerLane:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct Vertex
	{
       float x,y,z;//3个顶点
	   float r,g,b;
	};

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        
      
        Vertex rect[] = 
		{
			{10,   10,  0, 1, 0, 0},
			{110,  10,  0, 0, 1, 0},
			{160,  30,  0, 0, 0, 1},
			{200, 110,  0, 1, 0, 1},
            {160, 180,  0, 1, 0, 1},
		};
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);//启用颜色数组
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),rect); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glColorPointer(3,GL_FLOAT,sizeof(Vertex),&rect[0].r);
		glDrawArrays(GL_LINE_LOOP,0,5);//从0开始,共360*3个点
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerLane instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
GL LINE LOOP画5条线
















11月29日

  • 圆线的绘制(对线绘制的巩固)
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>

//用GL_LINES线段方式来画圆

class SamplerLane:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct Vertex
	{
       float x,y,z;//3个顶点
	   float r,g,b;
	};

	Vertex _circle[360 * 2];

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        
		float cx = 100;
        float cy = 100;
		float cz = 0;
		float r  = 80;
      
        for(int i = 0;i < 360; ++i)
		{
			_circle[i * 2 + 0].x  = r * cos(double(i) * M_PI / 180) + cx;
			_circle[i * 2 + 0].y  = r * sin(double(i) * M_PI / 180) + cy;
			_circle[i * 2 + 0].z  = cz;
            _circle[i * 2 + 0].r  = 1;
			_circle[i * 2 + 0].g  = 1;
			_circle[i * 2 + 0].b  = 1;

			_circle[i * 2 + 1].x  = r * cos(double(i + 1) * M_PI / 180) + cx;
			_circle[i * 2 + 1].y  = r * sin(double(i + 1) * M_PI / 180) + cy;
			_circle[i * 2 + 1].z  = cz;
			_circle[i * 2 + 1].r  = 1;
			_circle[i * 2 + 1].g  = 1;
			_circle[i * 2 + 1].b  = 1;
		}

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);//启用颜色数组
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),_circle); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glColorPointer(3,GL_FLOAT,sizeof(Vertex),&_circle[0].r);
		glDrawArrays(GL_LINES,0,sizeof(_circle)/sizeof(_circle[0]));//
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerLane instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
GL LINE线段方式画圆
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>

//用GL_LINES线带方式来画圆

class SamplerLane:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct Vertex
	{
       float x,y,z;//3个顶点
	   float r,g,b;
	};

	Vertex _circle[361];

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        
		float cx = 100;
        float cy = 100;
		float cz = 0;
		float r  = 80;
      
        for(int i = 0;i <= 360; ++i)
		{
			_circle[i].x  = r * cos(double(i) * M_PI / 180) + cx;
			_circle[i].y  = r * sin(double(i) * M_PI / 180) + cy;
			_circle[i].z  = cz;
            _circle[i].r  = 1;
			_circle[i].g  = 1;
			_circle[i].b  = 1;

		}

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);//启用颜色数组
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),_circle); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glColorPointer(3,GL_FLOAT,sizeof(Vertex),&_circle[0].r);
		glDrawArrays(GL_LINE_STRIP,0,sizeof(_circle)/sizeof(_circle[0]));//
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerLane instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
GL LINE STRIP线带画圆
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>

//用GL_LINE_LOOP闭合方式来画圆

class SamplerLane:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct Vertex
	{
       float x,y,z;//3个顶点
	   float r,g,b;
	};

	Vertex _circle[360];

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        
		float cx = 100;
        float cy = 100;
		float cz = 0;
		float r  = 80;
      
        for(int i = 0;i < 360; ++i)
		{
			_circle[i].x  = r * cos(double(i) * M_PI / 180) + cx;
			_circle[i].y  = r * sin(double(i) * M_PI / 180) + cy;
			_circle[i].z  = cz;
            _circle[i].r  = 1;
			_circle[i].g  = 1;
			_circle[i].b  = 1;

		}

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);//启用颜色数组
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),_circle); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glColorPointer(3,GL_FLOAT,sizeof(Vertex),&_circle[0].r);
		glDrawArrays(GL_LINE_LOOP,0,sizeof(_circle)/sizeof(_circle[0]));//
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerLane instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
GL LINE LOOP闭合画圆
















  • 贝塞尔曲线的绘制
贝塞尔曲线二次方公式:
    二次方贝兹曲线的路径由给定点P0、P1、P2的函数B(t)追踪:B(t)=(1-t)²P₀+2t(1-t)P₁+t²P₂,t∈[0,1]
贝塞尔曲线三次方公式:
    P0、P1、P2、P3四个点在平面或在三维空间中定义了三次方贝兹曲线。曲线起始于P0走向P1,并从P2的方向来到P3。一般不会经过P1或P2;这两个点只是在那里提供方向资讯。P0和P1之间的间距,决定了曲线在转而趋进P3之前,走向P2方向的“长度有多长”。
    B(t)=P₀(1-t)³+3P₁t(1-t)²+3P₂t²(1-t)+P₃t³,t∈[0,1]
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>

//用GL_LINE_LOOP闭合方式来画圆

class SamplerLane:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct Vertex
	{
       float x,y,z;//3个顶点
	};

	Vertex _line[360];

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        
		Vertex p0 = {10,10,0};
        Vertex p1 = {100,100,0};
		Vertex p2 = {200,10,0};

		int indx = 0;
		for (float t = 0;t < 1.0f;t += 0.01f, ++indx)
		{
			_line[indx].x  =  (1-t)*(1-t)*p0.x+2*t*(1-t)*p1.x+t*t*p2.x;
            _line[indx].y  =  (1-t)*(1-t)*p0.y+2*t*(1-t)*p1.y+t*t*p2.y;
			_line[indx].z  =  0;
		}

		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),_line); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_LINE_STRIP,0,indx - 1);//
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerLane instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
三点-贝塞尔曲线
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>

//用GL_LINE_LOOP闭合方式来画圆

class SamplerLane:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct Vertex
	{
       float x,y,z;//3个顶点
	};

	Vertex _line[360];

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        
		Vertex p0 = {10,10,0};
        Vertex p1 = {100,100,0};
		Vertex p2 = {200,10,0};
        Vertex p3 = {300,150,0};

		int indx = 0;
		for (float t = 0;t < 1.0f;t += 0.01f, ++indx)
		{
			_line[indx].x  =  (1-t)*(1-t)*(1-t)*p0.x+3*p1.x*t*(1-t)*(1-t)+3*p2.x*t*t*(1-t)+p3.x*t*t*t;
            _line[indx].y  =  (1-t)*(1-t)*(1-t)*p0.y+3*p1.y*t*(1-t)*(1-t)+3*p2.y*t*t*(1-t)+p3.y*t*t*t;
			_line[indx].z  =  0;
		}

		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),_line); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_LINE_STRIP,0,indx - 1);//
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerLane instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
四点-贝塞尔曲线
















11月30日

  • 矩形带的绘制
矩形带找点
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>


class SamplerLane:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct Vertex
	{
       float x,y,z;//3个顶点
	};


	//在此实现绘制
	virtual void render()
	{
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
  
		Vertex vertex[]  =  
		{
			{10,110,0},
			{10,10,0},

			{110,110,0},
			{110,10,0},

			{210,110,0},
			{210,10,0},	
		};
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),vertex); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_QUAD_STRIP,0,sizeof(vertex)/sizeof(vertex[0]));//
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerLane instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
矩形带绘制
















  • 不规则多边形的绘制(GL_POLYGON)
  思路:画多边形内部做些算法处理,将多边形切分成三角形处理
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>

//画凸多边形
class Samplerlygon:public OpenGLWindow
{
public:
	//描述一个顶点数据
	struct Vertex
	{
		float x,y,z;//3个顶点
	};


	//在此实现绘制
	virtual void render()
	{
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射

		Vertex vertex[]  =  
		{
			{50,0,0},
			{100,50,0},

			{80,100,0},
			{60,100,0},

			{10,50,0},
		};
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),vertex); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_POLYGON,0,sizeof(vertex)/sizeof(vertex[0]));//用GL_TRIANGLE_FAN处理效果一样
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	Samplerlygon instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
多边形绘制
















  • spline自由曲线的绘制
 需要先引入一个封装好的头文件CELLMath.hpp
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>

#include "CELLMath.hpp"
#include "OpenGLWindow.h"

#include <vector>
using namespace CELL;

class SamplerSpline:public OpenGLWindow
{
public:

	tspline<float> _spline;

	SamplerSpline()
	{
		_spline.addPoint(float3(10,10,0));
		_spline.addPoint(float3(20,100,0));
		_spline.addPoint(float3(100,80,0));
		_spline.addPoint(float3(200,100,0));
		_spline.addPoint(float3(300,10,0));
		_spline.addPoint(float3(400,150,0));

		for(float t = 0;t < 1.0f;t += 0.01f)
		{
			float3 pos = _spline.interpolate(t);
			_array.push_back(pos);
		}
	}

	std::vector<float3> _array;

	//在此实现绘制
	virtual void render()
	{
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        //关键点:
		
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),&_array[0]); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_LINE_STRIP,0,_array.size());//用GL_TRIANGLE_FAN处理效果一样
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerSpline instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
Spline自由曲线
















12月1日

  • spline曲线编辑(鼠标拖动修改关键点)
 先画出关键点:
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>

#include "CELLMath.hpp"
#include "OpenGLWindow.h"

#include <vector>
using namespace CELL;

class SamplerSplineEditor:public OpenGLWindow
{
public:

	tspline<float> _spline;
	SamplerSplineEditor()
	{
		_spline.addPoint(float3(10,10,0));
		_spline.addPoint(float3(20,100,0));
		_spline.addPoint(float3(100,80,0));
		_spline.addPoint(float3(200,100,0));
		_spline.addPoint(float3(300,10,0));
		_spline.addPoint(float3(400,150,0));

		for(float t = 0;t < 1.0f;t += 0.01f)
		{
			float3 pos = _spline.interpolate(t); //插值
			_array.push_back(pos);//将一个新的元素加到vector的最后面
		}
        for(int i = 0;i<_spline.getNumPoints(); ++i)
		{
            _keys.push_back(_spline.getPoint(i));
		}
	}
	std::vector<float3> _array;
	std::vector<float3> _keys;

	//在此实现绘制
	virtual void render()
	{
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        //关键点:
		
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),&_array[0]); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_LINE_STRIP,0,_array.size());//用GL_TRIANGLE_FAN处理效果一样

		glPointSize(8);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),&_keys[0]); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_POINTS,0,_keys.size());//用GL_TRIANGLE_FAN处理效果一样
	    
	}
    //重写event()函数
	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_CLOSE:
		case WM_DESTROY:
			{
				PostQuitMessage(0);
			}
			break;
		case WM_LBUTTONDOWN://鼠标按下消息
				break;
		case WM_LBUTTONUP://鼠标抬起消息
				break;
		case WM_MOUSEMOVE://鼠标移动消息
                break;
		default:
			return DefWindowProc(hWnd,msgId,wParam,lParam);
		}
		return 0;
	}
};
//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerSplineEditor instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
关键点















 再完成可编辑:
//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>

#include "CELLMath.hpp"
#include "OpenGLWindow.h"

#include <vector>
using namespace CELL;

class SamplerSplineEditor:public OpenGLWindow
{
public:

	tspline<float> _spline;
	bool           _isButtonDown;
	size_t         _selectIndex; //记录当前选中的点

	POINT          _mouse0Id; //记录鼠标按下的点

    std::vector<float3> _array;
	std::vector<float3> _keys;//关键点
	
	SamplerSplineEditor()
	{
		_isButtonDown    =   false;
        _selectIndex     =  -1;

		_spline.addPoint(float3(10,10,0));
		_spline.addPoint(float3(20,100,0));
		_spline.addPoint(float3(100,80,0));
		_spline.addPoint(float3(200,100,0));
		_spline.addPoint(float3(300,10,0));
		_spline.addPoint(float3(400,150,0));

		//将点加到_array中
		for(float t = 0;t < 1.0f;t += 0.01f)
		{
			float3 pos = _spline.interpolate(t); //插值
			_array.push_back(pos);//将一个新的元素加到_array的最后面
		}
		//将关键点加入_keys里来
        for(int i = 0;i<_spline.getNumPoints(); ++i)//getNumPoints()得到点的个数
		{
            _keys.push_back(_spline.getPoint(i));
		}
	}

	

	//在此实现绘制
	virtual void render()
	{
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
		
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),&_array[0]); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_LINE_STRIP,0,_array.size());

		glPointSize(8);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),&_keys[0]); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_POINTS,0,_keys.size());
	    
	}
    //重写event()函数
	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_CLOSE:
		case WM_DESTROY:
			{
				PostQuitMessage(0);
			}
			break;
		case WM_LBUTTONDOWN://鼠标按下消息
			{
				_isButtonDown  = true;
                _selectIndex   =  -1;
				//得到鼠标的位置
				POINT pt = {LOWORD(lParam),HIWORD(lParam)};//低字节存着坐标x,高字节存着坐标y
			    _mouse0Id = pt;
				
				//以关键点生成矩形
				for(size_t i = 0;i< _keys.size(); ++i)
				{
                           RECT rt;
						   rt.left = _keys[i].x - 4;
                           rt.right = _keys[i].x + 4;
						   rt.top = _keys[i].y - 4;
						   rt.bottom = _keys[i].y + 4;
				
				//循环鼠标是否点中了矩形
				      if(PtInRect(&rt,pt))
				    {
                      _selectIndex  = i;
				      break;
				    }
				}
			}
				break;
		case WM_LBUTTONUP://鼠标抬起消息
			{
				_isButtonDown    =   false;
				_selectIndex     =  -1;
			}

				break;
		case WM_MOUSEMOVE://鼠标移动消息
			{
                if(_isButtonDown && _selectIndex !=-1)
				{
                  POINT pt  = {LOWORD(lParam),HIWORD(lParam)};
				  
				  POINT off = {pt.x - _mouse0Id.x,pt.y -_mouse0Id.y};//移动后-之前
				  
				  _mouse0Id =pt; //将_mouse0Id置位

				  //将偏移量应用到选中的点上
				  _keys[_selectIndex].x += off.x;
                  _keys[_selectIndex].y += off.y; //改变绘制的大小

				  _spline.getPoint(_selectIndex).x += off.x;
				  _spline.getPoint(_selectIndex).y += off.y;//改变曲线里的大小
   
				  _spline.recalcTangents();//重新计算

				  _array.clear();

				  //同时更新计算
				  for(float t = 0;t < 1.0f;t += 0.01f)
				  {
					  float3 pos = _spline.interpolate(t); //插值
					  _array.push_back(pos);//将一个新的元素加到vector的最后面
				  }
				}
			}
                break;
		default:
			return DefWindowProc(hWnd,msgId,wParam,lParam);
		}
		return 0;
	}


};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerSplineEditor instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
spline曲线编辑(鼠标拖动修改关键点)
















12月2日

总结:
1、size_t是一些C/C++标准在stddef.h中定义的;size_t的真实类型与操作系统有关。size_t一般用来表示一种计数,比如有多少东西被拷贝等。
2、PostQuitMessage函数通知系统当前有一个线程发送了进程中止退出请求.它典型的使用在WM_DESTROY消息处理中.
  • 线样式的应用,实线,虚线,点划线
        glColor3f(1,0,0);
	glLineWidth(1);//线宽
	glEnable(GL_LINE_STIPPLE);
	glLineStipple(1,0xFF00);//factor:重复率 pattern:样式(主要关注);0xFF00十六进制short类型
  • 运行:
线的样式
















12月3日

  • 平滑处理-反锯齿的应用
OpenGL中glEnable()常用的参数:
   GL_BLEND:       启用颜色混合。例如实现半透明效果
   GL_LINE_SMOOTH: 执行后,过虑线段的锯齿
   GL_LINE_STIPPLE:执行后,画虚线
   GL_POINT_SMOOTH:执行后,过虑线点的锯齿
glBlendFunc()函数的使用: https://blog.csdn.net/Qinhaifu/article/details/100132568
          glEnable(GL_LINE_SMOOTH);//对线进行抗锯齿处理
	  glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);//指定反锯齿的算法,锯齿处理
	  glEnable(GL_BLEND);
          glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_DST_ALPHA);//源颜色乘以自身的alpha 值,目标颜色乘以1.0减去源颜色的alpha值
  • 运行:
平滑处理
      //对点进行抗锯齿处理
        glEnable(GL_POINT_SMOOTH);
        glHint(GL_POINT_SMOOTH,GL_NICEST);//指定反锯齿的算法,锯齿处理
  • 运行:
平滑处理(点)









完整代码:

//lesson204.cpp
#include "OpenGLWindow.h"
#include <math.h>

#include "CELLMath.hpp"
#include "OpenGLWindow.h"

#include <vector>
using namespace CELL;

class SamplerSmooth:public OpenGLWindow
{
public:

	tspline<float> _spline;
	bool           _isButtonDown;
	size_t         _selectIndex; //记录当前选中的点

	POINT          _mouse0Id; //记录鼠标按下的点

    std::vector<float3> _array;
	std::vector<float3> _keys;//关键点
	
	SamplerSmooth()
	{
		_isButtonDown    =   false;
        _selectIndex     =  -1;

		_spline.addPoint(float3(10,10,0));
		_spline.addPoint(float3(20,100,0));
		_spline.addPoint(float3(100,80,0));
		_spline.addPoint(float3(200,100,0));
		_spline.addPoint(float3(300,10,0));
		_spline.addPoint(float3(400,150,0));

		//将点加到_array中
		for(float t = 0;t < 1.0f;t += 0.01f)
		{
			float3 pos = _spline.interpolate(t); //插值
			_array.push_back(pos);//将一个新的元素加到_array的最后面
		}
		//将关键点加入_keys里来
        for(int i = 0;i<_spline.getNumPoints(); ++i)//getNumPoints()得到点的个数
		{
            _keys.push_back(_spline.getPoint(i));
		}
	}

	

	//在此实现绘制
	virtual void render()
	{
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
		//样式:
		glColor3f(1,0,0);
		glLineWidth(1);//线宽
		
		glEnable(GL_LINE_SMOOTH);//对线进行抗锯齿处理
		glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);//指定反锯齿的算法,锯齿处理
		glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_DST_ALPHA);//源颜色乘以自身的alpha 值,目标颜色乘以1.0减去源颜色的alpha值
		
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),&_array[0]); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_LINE_STRIP,0,_array.size());

		glEnable(GL_POINT_SMOOTH);//对点进行抗锯齿处理
		glHint(GL_POINT_SMOOTH,GL_NICEST);//指定反锯齿的算法,锯齿处理


		glPointSize(8);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),&_keys[0]); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glDrawArrays(GL_POINTS,0,_keys.size());
	    
	}
    //重写event()函数
	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_CLOSE:
		case WM_DESTROY:
			{
				PostQuitMessage(0);
			}
			break;
		case WM_LBUTTONDOWN://鼠标按下消息
			{
				_isButtonDown  = true;
                _selectIndex   =  -1;
				//得到鼠标的位置
				POINT pt = {LOWORD(lParam),HIWORD(lParam)};//低字节存着坐标x,高字节存着坐标y
			    _mouse0Id = pt;
				
				//以关键点生成矩形
				for(size_t i = 0;i< _keys.size(); ++i)
				{
                           RECT rt;
						   rt.left = _keys[i].x - 4;
                           rt.right = _keys[i].x + 4;
						   rt.top = _keys[i].y - 4;
						   rt.bottom = _keys[i].y + 4;
				
				//循环鼠标是否点中了矩形
				      if(PtInRect(&rt,pt))
				    {
                      _selectIndex  = i;
				      break;
				    }
				}
			}
				break;
		case WM_LBUTTONUP://鼠标抬起消息
			{
				_isButtonDown    =   false;
				_selectIndex     =  -1;
			}

				break;
		case WM_MOUSEMOVE://鼠标移动消息
			{
                if(_isButtonDown && _selectIndex !=-1)
				{
                  POINT pt  = {LOWORD(lParam),HIWORD(lParam)};
				  
				  POINT off = {pt.x - _mouse0Id.x,pt.y -_mouse0Id.y};
				  
				  _mouse0Id =pt; //将_mouse0Id置位

				  //将偏移量应用到选中的点上
				  _keys[_selectIndex].x += off.x;
                  _keys[_selectIndex].y += off.y; //改变绘制的大小

				  _spline.getPoint(_selectIndex).x += off.x;
				  _spline.getPoint(_selectIndex).y += off.y;//改变曲线里的大小
   
				  _spline.recalcTangents();//重新计算

				  _array.clear();

				  //同时更新计算
				  for(float t = 0;t < 1.0f;t += 0.01f)
				  {
					  float3 pos = _spline.interpolate(t); //插值
					  _array.push_back(pos);//将一个新的元素加到vector的最后面
				  }
				}
			}
                break;
		default:
			return DefWindowProc(hWnd,msgId,wParam,lParam);
		}
		return 0;
	}


};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerSmooth instance;
	instance.main(800,600);

	return 0;
}
  • 图片的绘制
//lesson206.cpp
#include "OpenGLWindow.h"
#include <math.h>
//创建win32窗口

class SamplerDrawPixel:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct float3
	{
       float x,y,z;//3个顶点
	   float w;
	};

    char*  _pixel;

	SamplerDrawPixel()
	{
       _pixel = new char[100 * 200 * 4];
	   for(int i = 0;i < 100 * 200 * 4;++i)
	   {
		   _pixel[i]  =  rand()%255;
	   }
	}

	float3 _circle[362];

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        glColor3f(1,1,1);
      
        float3 rect[] = 
		{
			{10,  10,   0},
			{110, 10,   0},
			{10,  110,  0},
			{110, 110,  0}
		};
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),rect); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glDrawArrays(GL_TRIANGLE_STRIP,0,4);//从0开始,共360*3个点
	
		glRasterPos2i(100,300);//在窗口的位置
	    glDrawPixels(100,200,GL_RGBA,GL_UNSIGNED_BYTE,_pixel);//此函数效率低,少用;GL_UNSIGNED_BYTE存char类型数据
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerDrawPixel instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
图片的绘制
















  • OpenGL扩展的使用,获取最新的显卡特性
char* ext = (char*)glGetString(GL_EXTENSIONS);//GL_EXTENSIONS返回当前显卡所支持的全部扩展

12月4日

项目属性--配置属性--C/C++--预处理器--预处理器定义:添加EW_STATIC

#pragma once

#include "GLContext.h"

class OpenGLWindow:public GLContext
{
protected:
	int _width;
	int _height;
public:
    OpenGLWindow(HINSTANCE hInst = 0)
	{
		//1注册窗口类
		WNDCLASSEX wnd;

		memset(&wnd,0,sizeof(wnd));

		wnd.cbSize          =   sizeof(wnd); //指明当前结构体大小
		wnd.lpfnWndProc     =   wndProc; //函数指针,若有事件发生,则调此函数
		wnd.hbrBackground   =   (HBRUSH)GetStockObject(GRAY_BRUSH);
		wnd.hCursor         =   LoadCursor(hInst,IDC_ARROW);//鼠标样式
		wnd.hIcon           =   0;
		wnd.hIconSm         =   0;
		wnd.hInstance       =   0;
		wnd.lpszClassName   =   _T("窗口标题"); 
		wnd.style           =   CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
		RegisterClassEx(&wnd);  //调用注册窗口类函数
	
	}
	virtual void onInitGL()
	{

	}

    virtual	bool main(int w,int h)
	{
		//2创建窗口
	HWND	hWnd  =   CreateWindowEx(
			0 // 窗口的扩展风格
			,_T("窗口标题")//需和wnd.lpszClassName一致
			,_T("窗口标题")//窗口标题
			,WS_OVERLAPPEDWINDOW//窗口风格,有无最大化最小化
			,0//窗口在屏幕的位置
			,0//窗口在屏幕的位置
			,w//宽
			,h//高
			,0//系统菜单
			,0//父窗口
			,0//实例句柄
			,this);//用户数据,用户自定义 this指当前对象
		//3更新显示
		if(hWnd)
		{
			UpdateWindow(hWnd);
			ShowWindow(hWnd,SW_SHOW);
		}
		else
		{
			return false;
		}

		if(!setup(hWnd,GetDC(hWnd)))
		{
			return false;
		}

     onInitGL();

		MSG  msg={0};
		//4消息循环
		while(WM_QUIT !=msg.message)
		{
			if(PeekMessage(&msg,0,0,0,PM_REMOVE))//有消息产生;点关闭按钮,返回值为false
			{
				TranslateMessage(&msg);//翻译
				DispatchMessage(&msg);//分发
			}
			else
			{
				RECT rect;
				GetClientRect(hWnd,&rect);
				_width  =  rect.right  -  rect.left;
				_height =  rect.bottom -  rect.top;

				glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
				glViewport(0,0,_width,_height);

				render();
				swapBuffer();
			}
		}
		shutdown();

		return true;
	}

	virtual void render()
	{

	}
     /*消息处理过程*/
	
    virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_CLOSE:
		case WM_DESTROY:
			{
				PostQuitMessage(0);
			}
			break;
		default:
			return DefWindowProc(hWnd,msgId,wParam,lParam);
		}
		return 0;
	}

protected:
	static LRESULT CALLBACK wndProc(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam) //创建窗口之前可能消息已经来了,lParam里携带了this指针
	{
        if(msgId == WM_CREATE)
		{
           LPCREATESTRUCT  pData  =  (LPCREATESTRUCT)lParam;// LPCREATESTRUCT本身是指针
		   OpenGLWindow*   pTHis  =  (OpenGLWindow*)pData->lpCreateParams;
		   SetWindowLong(hWnd,GWL_USERDATA,(LONG)pTHis);//在当前窗口上关联了一个用户数据pTHis,window和变量关联放入GWL_USERDATA槽中
		   return DefWindowProc(hWnd,msgId,wParam,lParam);
		}
		else
		{
           OpenGLWindow*   pTHis  =  (OpenGLWindow*)GetWindowLong(hWnd,GWL_USERDATA);
		   if(pTHis)
		   {
            return pTHis->events(hWnd,msgId,wParam,lParam);
		   }
		   else
		   {
            return DefWindowProc(hWnd,msgId,wParam,lParam); //调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理;该函数确保每一个消息得到处理
		   }   
		}
	}
};
//lesson206.cpp

#include "glew/glew.h"
#include "OpenGLWindow.h"
#include <math.h>


//创建win32窗口

class SamplerExt:public OpenGLWindow
{
public:
    //描述一个顶点数据
    struct float3
	{
       float x,y,z;//3个顶点
	   float w;
	};

    char*  _pixel;

	SamplerExt()
	{
      
	}
    virtual void onInitGL()
	{
       glewInit();
	}
	float3 _circle[362];

	//在此实现绘制
	virtual void render()
	{
        char* ext = (char*)glGetString(GL_EXTENSIONS);//GL_EXTENSIONS返回当前显卡所支持的全部扩展

        #define M_PI (3.14159265358979323846)
        
        PFNGLARRAYELEMENTEXTPROC glArrayElementEXT = (PFNGLARRAYELEMENTEXTPROC)wglGetProcAddress("glArrayElementEXT");
        glArrayElementEXT(0);//调用函数

		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
        glColor3f(1,1,1);
      
        float3 rect[] = 
		{
			{10,  10,   0},
			{110, 10,   0},
			{10,  110,  0},
			{110, 110,  0}
		};
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),rect); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glDrawArrays(GL_TRIANGLE_STRIP,0,4);//从0开始,共360*3个点
	
		glRasterPos2i(100,300);//在窗口的位置
	    glDrawPixels(100,200,GL_RGBA,GL_UNSIGNED_BYTE,_pixel);//此函数效率低,少用;GL_UNSIGNED_BYTE存char类型数据
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerExt instance;
	instance.main(800,600);

	return 0;
}
  • 以上代码实现将glew加入库中,扩展可直接调用



  • 突破帧率限制(垂直同步控制)[扩展的应用]
   垂直同步的作用是让显卡的运算和显示器刷新率一致以稳定输出的画面质量,就是说显示器能够支持的刷新率是多少,显卡运算的帧率也就多少,
//lesson206.cpp

#include <math.h>
#include "glew/glew.h"
#include "glew/wglew.h"
#include "OpenGLWindow.h"

//创建win32窗口

class SamplerExt:public OpenGLWindow
{
public:
	//描述一个顶点数据
	struct Vertex
	{
		float x,y,z;//3个顶点
		float r,g,b;
	};

	char*  _pixel;

	SamplerExt()
	{

	}
	virtual void onInitGL()
	{
		glewInit();
	//	wglSwapIntervalEXT(0);//OpenGL的扩展函数;0:关闭垂直同步;1:打开垂直同步

	}

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)

		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		glOrtho(0,_width,_height,0,-100,100);//产生投影矩阵;left=0,整个窗口映射
		glColor3f(1,1,1);

		Vertex rect[] = 
		{
			{10,  10,   0, 1, 0, 0},
			{110, 10,   0, 0, 1, 0},
			{10,  110,  0, 0, 0, 1},
			{110, 110,  0, 1, 0, 1}
		};
		//glColor3f(1,0,1);
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),rect); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),&rect[0].r);
		glDrawArrays(GL_TRIANGLE_STRIP,0,4);//从0开始
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerExt instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
关垂直同步
开垂直同步

















12月5日

  • 全屏幕反锯齿的应用(OpenGL扩展)
#pragma once
//在win32窗口下建立OPenGL的开发环境
#include <Windows.h>
#include <tchar.h>

#include "glew/glew.h"
#include "glew/wglew.h"
#include <gl/gl.h>

//OpenGL的标准头文件

class GLContext
{
protected:
	int    _format;
	HWND   _hWnd; //窗口句柄
	HDC    _hDC;//绘制设备上下文
	HGLRC  _hRC;//OpenGL上下文
public:

	GLContext(void)
	{
       _format  =   0;
       _hWnd    =   0; 
       _hDC     =   0; 
       _hRC     =   0; 


	}

	~GLContext(void)
	{
		shutdown();
	}
//初始化GL
	bool setup(HWND hWnd,HDC hDC){
      _hWnd  =  hWnd;
      _hDC   =  hDC;
	  unsigned PixelFormat;
	  //像素的格式描述符
	  PIXELFORMATDESCRIPTOR pfd = 
	  {
         sizeof(PIXELFORMATDESCRIPTOR),
		 1,//版本,window支持1
		 PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |PFD_DOUBLEBUFFER,
		 PFD_TYPE_RGBA,//像素类型 不采用索引(4个通道,每个通道占8个bit位)
		 32,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 0,
		 24,//深度缓冲区
		 8,//模板缓冲区
		 0,//累计缓存
		 PFD_MAIN_PLANE,//直接写到屏幕上
		 0,
		 0,
		 0,
		 0
	  };
	  if(_format == 0) //初始化
	  {
		  //得到索引(调windows的API)
		  PixelFormat = ChoosePixelFormat(_hDC,&pfd); //在_hDC上匹配pfd
	  }
	  else
	  {
		  PixelFormat = _format;
	  }
	  if(!SetPixelFormat(_hDC,PixelFormat,&pfd))
	  {
		  return false;
	  }
	  //返回的OpenGL的上下文句柄
	  _hRC  =  wglCreateContext(_hDC); //在给定的DC上建立上下文
	 
	  if(!wglMakeCurrent(_hDC,_hRC))
	  {
		  return false;
	  }

      glewInit();
	  
	  int format = setupMultisample(); //得到格式串索引

	  if(_hRC != NULL) //销毁当前OpenGL上下文
	  {
		  wglMakeCurrent(_hDC,NULL);
		  wglDeleteContext(_hRC);
		  _hRC=NULL;
	  }
    
	  if(!SetPixelFormat(_hDC,format,&pfd)) //重新建立格式
	  {
		  return false;
	  }

	  _hRC  =  wglCreateContext(_hDC); //在给定的DC上建立上下文

	  if(!wglMakeCurrent(_hDC,_hRC))
	  {
		  return false;
	  }
	 

	  return true;
	}

   int setupMultisample() //建立多采样
   {
	   if(wglChoosePixelFormatARB  == 0)//= 0不支持全局反锯齿
	   {
		   return 0;
	   }
       int   pixelFormat;
	   int   valid;
	   UINT  numFormats;
	   float fAttributes[] = {0,0};


	   int iAttributes[] = //属性列表
	   {
		   WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
		   WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
		   WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
		   WGL_COLOR_BITS_ARB,24,
		   WGL_ALPHA_BITS_ARB,8,
		   WGL_DEPTH_BITS_ARB,16,
		   WGL_STENCIL_BITS_ARB,0,
		   WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
		   WGL_SAMPLE_BUFFERS_ARB,GL_TRUE, //支持多采样(反锯齿)
		   WGL_SAMPLES_ARB,4, //最重要  采样的频度,4:4倍采样
		   0,0 //结束
	   };
	   //调OpenGL扩展的API
	   valid = wglChoosePixelFormatARB(_hDC,iAttributes,fAttributes,1,&pixelFormat,&numFormats);//返回值:&pixelFormat(像素格式);返回值不为0表示索引成功了
	   
	   if(valid && numFormats >= 1)
	   {
		   return pixelFormat;
	   }
       iAttributes[19] = 2; //失败了就把采样的频度改成2
	  
	   valid = wglChoosePixelFormatARB(_hDC,iAttributes,fAttributes,1,&pixelFormat,&numFormats);//返回值:&pixelFormat(像素格式)返回支持iAttributes[]的索引;返回值不为0表示索引成功了
	 
	   if(valid && numFormats >= 1)
	   {
		   return pixelFormat;
	   }
	   return 0;
   }

//销毁EGL
	void shutdown(){
      if(_hRC != NULL)
	  {
		  wglMakeCurrent(NULL,NULL);
		  wglDeleteContext(_hRC);
		  _hRC=NULL;
	  }
	  if(_hDC != NULL)
	  {
		  ReleaseDC(_hWnd,_hDC);
		  _hDC=NULL;
	  }

	}
//交换缓冲区
	void swapBuffer(){
     SwapBuffers(_hDC);
	}
};
  • 第三章:三维世界


  • 透视投影
//OpenGL函数
   void gluPerspective(  //OpenGL提供的一个单元库
      GLdouble fovy, //角度
      GLdouble aspect,//宽高比
      GLdouble zNear, //裁剪面
      GLdouble zFar, //裁剪面
       );

12月6日

//lesson206.cpp

#include "glew/glew.h"
#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <math.h>

#include <vector>
using namespace CELL;

//创建win32窗口

class SamplerPerspective:public OpenGLWindow
{
public:

	SamplerPerspective() 
	{

	}

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
      
        float3 arVert[] = 
		{
			float3(0.5f,0,-1),
            float3(0.2f,0.3,-1),
            float3(0.8f,0.3,-1),
		};
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(float3),arVert); //提供更高效的数据传递方法;第三个参数为偏移量;为0则是偏移3*float
	    glDrawArrays(GL_TRIANGLES,0,3);//从0开始
	
		glRasterPos2i(100,300);//在窗口的位置
	    glDrawPixels(100,200,GL_RGBA,GL_UNSIGNED_BYTE,arVert);//此函数效率低,少用;GL_UNSIGNED_BYTE存char类型数据
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerPerspective instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
透视投影--三角形















建立的摄像机,向屏幕里面看去是负值,向屏幕外面看去是正值

12月7日

  • 绘制一个正方体,并上色
//lesson206.cpp

#include "glew/glew.h"
#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <math.h>

#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex //共占16个字节
{
	unsigned char r,g,b,a;//每一个占1个字节
	float x,y,z;
};

class SamplerColorCube:public OpenGLWindow
{
public:

	SamplerColorCube() 
	{

	}

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
      
		Vertex cubeVertices[] =
		{
			{255,0,0,255, -1.0f,-1.0f,1.0f},
            {255,0,0,255,  1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f, 1.0f,1.0f},
			{255,0,0,255, -1.0f, 1.0f,1.0f},

			{0,255,0,255,-1.0f,-1.0f,-1.0f},
			{0,255,0,255,-1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f,-1.0f,-1.0f},

			{0,0,255,255, -1.0f, 1.0f,  -1.0f },
			{0,0,255,255, -1.0f, 1.0f,  1.0f },
			{0,0,255,255, 1.0f, 1.0f,   1.0f },
			{0,0,255,255, 1.0f, 1.0f,   -1.0f },

			{0,255,255,255, -1.0f,-1.0f,  -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   1.0f  },
			{0,255,255,255, -1.0f,-1.0f,  1.0f  },

			{255,0,255,255,  1.0f,-1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  1.0f  },
			{255,0,255,255,  1.0f,-1.0f,  1.0f  },

			{255,255,255,255, -1.0f,-1.0f,  -1.0f },
			{255,255,255,255, -1.0f,-1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  -1.0f }


		};

		for(int i=0;i<24;++i)
		{
           cubeVertices[i].z  -= 5;
		}
#if 0
        glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_C4UB_V3F, 0,cubeVertices);

#else 
		glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
	    glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
	    glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex),cubeVertices);
#endif
		glDrawArrays(GL_QUADS,0,24);//从0开始
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerColorCube instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
带颜色的正方体
















  • 当没有深度测试时,是下图
异常正方体(没有启动异常测试)















#if 1
         glEnable(GL_DEPTH_TEST);//深度测试
	 glInterleavedArrays(GL_C4UB_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应
#else 
	 glEnable(GL_DEPTH_TEST);//深度测试
	 glEnableClientState(GL_VERTEX_ARRAY);
         glEnableClientState(GL_COLOR_ARRAY);
	 glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
	 glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex),cubeVertices);
#endif
第一种方法效率更高,第二种方法更灵活一些
  • 矩阵变换-平移矩阵
 平移、旋转、缩放都是对模型矩阵进行操作
 模型矩阵、投影矩阵、观察矩阵组成三维的理论
//lesson206.cpp

#include "glew/glew.h"
#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <math.h>

#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex //共占16个字节
{
	unsigned char r,g,b,a;//每一个占1个字节
	float x,y,z;
};

class SamplerTranslate:public OpenGLWindow
{
public:

	SamplerTranslate() 
	{

	}

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
      
		Vertex cubeVertices[] =
		{
			{255,0,0,255, -1.0f,-1.0f,1.0f},
            {255,0,0,255,  1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f, 1.0f,1.0f},
			{255,0,0,255, -1.0f, 1.0f,1.0f},

			{0,255,0,255,-1.0f,-1.0f,-1.0f},
			{0,255,0,255,-1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f,-1.0f,-1.0f},

			{0,0,255,255, -1.0f, 1.0f,  -1.0f },
			{0,0,255,255, -1.0f, 1.0f,  1.0f },
			{0,0,255,255, 1.0f, 1.0f,   1.0f },
			{0,0,255,255, 1.0f, 1.0f,   -1.0f },

			{0,255,255,255, -1.0f,-1.0f,  -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   1.0f  },
			{0,255,255,255, -1.0f,-1.0f,  1.0f  },

			{255,0,255,255,  1.0f,-1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  1.0f  },
			{255,0,255,255,  1.0f,-1.0f,  1.0f  },

			{255,255,255,255, -1.0f,-1.0f,  -1.0f },
			{255,255,255,255, -1.0f,-1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  -1.0f }
		};
		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
    //  glLoadIdentity();//将模型矩阵清成单位矩阵

		//产生一个矩阵
	//	glTranslatef(2,2,-10);//单位阵与产生的矩阵相乘还是单位阵

#if 1
        glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_C4UB_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
	    glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
	    glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex),cubeVertices);
#endif

		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵 * 当前矩阵
		glTranslatef(-2,2,-10);
		glDrawArrays(GL_QUADS,0,24);

		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵
		glTranslatef(2,2,-10);
		glDrawArrays(GL_QUADS,0,24);

		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵
		glTranslatef(5,2,-10);
		glDrawArrays(GL_QUADS,0,24);


	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTranslate instance;
	instance.main(800,600);

	return 0;
}
  • 运行
三个立方体
















12月8日

  • 矩阵变换-缩放矩阵
//lesson206.cpp

#include "glew/glew.h"
#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <math.h>

#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex //共占16个字节
{
	unsigned char r,g,b,a;//每一个占1个字节
	float x,y,z;
};

class SamplerTranslate:public OpenGLWindow
{
public:

	SamplerTranslate() 
	{

	}

	//在此实现绘制
	virtual void render()
	{
        #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
      
		Vertex cubeVertices[] =
		{
			{255,0,0,255, -1.0f,-1.0f,1.0f},
            {255,0,0,255,  1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f, 1.0f,1.0f},
			{255,0,0,255, -1.0f, 1.0f,1.0f},

			{0,255,0,255,-1.0f,-1.0f,-1.0f},
			{0,255,0,255,-1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f,-1.0f,-1.0f},

			{0,0,255,255, -1.0f, 1.0f,  -1.0f },
			{0,0,255,255, -1.0f, 1.0f,  1.0f },
			{0,0,255,255, 1.0f, 1.0f,   1.0f },
			{0,0,255,255, 1.0f, 1.0f,   -1.0f },

			{0,255,255,255, -1.0f,-1.0f,  -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   1.0f  },
			{0,255,255,255, -1.0f,-1.0f,  1.0f  },

			{255,0,255,255,  1.0f,-1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  1.0f  },
			{255,0,255,255,  1.0f,-1.0f,  1.0f  },

			{255,255,255,255, -1.0f,-1.0f,  -1.0f },
			{255,255,255,255, -1.0f,-1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  -1.0f }
		};
		////改变顶点数据进行放大
  //        for (int i=0;i<sizeof(cubeVertices)/sizeof(cubeVertices[0]);++i)
		//  {
		//	  cubeVertices[i].x *= 3;
  //          cubeVertices[i].y *= 3;
		//	  cubeVertices[i].z *= 3;
		//  }



		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
    //  glLoadIdentity();//将模型矩阵清成单位矩阵

		//产生一个矩阵
	//	glTranslatef(2,2,-10);//单位阵与产生的矩阵相乘还是单位阵

#if 1
        glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_C4UB_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
	    glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
	    glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex),cubeVertices);
#endif

		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵 * 当前矩阵
		glTranslatef(0,0,-10);
		//产生一个矩阵
                glScalef(1,2,2);

		glDrawArrays(GL_QUADS,0,24);

		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵
		glTranslatef(3,0,-10);
                glScalef(1,2,1);
		glDrawArrays(GL_QUADS,0,24);

		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵
		glTranslatef(3,-3,-10);
                glScalef(1,0.5,1);

		glDrawArrays(GL_QUADS,0,24);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTranslate instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
矩阵变换-缩放















                glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵 * 当前矩阵
		glTranslatef(0,0,-10);
		//产生一个矩阵
                glScalef(1,2,2);
		glDrawArrays(GL_QUADS,0,24);
注意:以上代码产生了两次矩阵乘法,矩阵左乘和右乘有区别
  • 矩阵变换-旋转矩阵
  glRotatef(_angle,1,1,1);//沿斜轴旋转
//lesson206.cpp

#include "glew/glew.h"
#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <math.h>

#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex //共占16个字节
{
	unsigned char r,g,b,a;//每一个占1个字节
	float x,y,z;
};

class SamplerRotate:public OpenGLWindow
{
public:
	float _angle;
public:
	SamplerRotate() 
	{
		_angle = 0;
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{255,0,0,255, -1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f, 1.0f,1.0f},
			{255,0,0,255, -1.0f, 1.0f,1.0f},

			{0,255,0,255,-1.0f,-1.0f,-1.0f},
			{0,255,0,255,-1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f,-1.0f,-1.0f},

			{0,0,255,255, -1.0f, 1.0f,  -1.0f },
			{0,0,255,255, -1.0f, 1.0f,  1.0f },
			{0,0,255,255, 1.0f, 1.0f,   1.0f },
			{0,0,255,255, 1.0f, 1.0f,   -1.0f },

			{0,255,255,255, -1.0f,-1.0f,  -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   1.0f  },
			{0,255,255,255, -1.0f,-1.0f,  1.0f  },

			{255,0,255,255,  1.0f,-1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  1.0f  },
			{255,0,255,255,  1.0f,-1.0f,  1.0f  },

			{255,255,255,255, -1.0f,-1.0f,  -1.0f },
			{255,255,255,255, -1.0f,-1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  -1.0f }
		};
		////改变顶点数据进行放大
		//        for (int i=0;i<sizeof(cubeVertices)/sizeof(cubeVertices[0]);++i)
		//  {
		//	  cubeVertices[i].x *= 3;
		//          cubeVertices[i].y *= 3;
		//	  cubeVertices[i].z *= 3;
		//  }

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		//  glLoadIdentity();//将模型矩阵清成单位矩阵

		//产生一个矩阵
		//	glTranslatef(2,2,-10);//单位阵与产生的矩阵相乘还是单位阵

#if 1
		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_C4UB_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex),cubeVertices);
#endif
		_angle += 1;
		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵 * 当前矩阵
		glTranslatef(0,0,-5);
		//产生一个矩阵
		glRotatef(_angle,1,0,0);

		glDrawArrays(GL_QUADS,0,24);

		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵
		glTranslatef(3,0,-10);
	    glRotatef(_angle,0,1,0);
		glDrawArrays(GL_QUADS,0,24);

		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵
		glTranslatef(3,-3,-10);
		glRotatef(_angle,0,0,1);

		glDrawArrays(GL_QUADS,0,24);


	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerRotate instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
矩阵变换-旋转


















12月9日

建立的摄像机,向屏幕里面看去是负值,向屏幕外面看去是正值(换言之,z的负值越大,模型越小)
平移、旋转、缩放都是对模型矩阵进行操作
模型矩阵、投影矩阵、观察矩阵组成三维的理论

总结:
投影变换概述

 投影变换完成的是如何将三维模型显示到二维视口上,这是一个三维到二维的过程。可以将投影变换看作是调整照相机的焦距,它模拟了为照相机选择镜头的过程。投影变换是所有变换中最复杂的一个。

视锥体

 视锥体是一个三维体,位置和摄像机相关;最常见的投影类型:透视投影,近大远小;透视投影使用棱锥作为视锥体,摄像机位于棱锥的椎顶。该棱锥被前后两个平面截断,形成一个棱台,叫做View Frustum,只有位于Frustum内部的模型才是可见的。
视锥体














透视投影的目的

 将上面的棱台转换为一个立方体(cuboid),转换后,棱台的前剪裁平面的右上角点变为立方体的前平面的中心(下图中弧线所示)。由图可知,这个变换的过程是将棱台较小的部分放大,较大的部分缩小,以形成最终的立方体。这就是投影变换会产生近大远小的效果的原因。变换后的x坐标范围是[-1, 1],y坐标范围是[-1, 1],z坐标范围是[0, 1](OpenGL略有不同,z值范围是[-1, 1])。
坐标说明










12月10日

平移、缩放、旋转梳理:

平移实现的两种方法:
① 通过改变模型内部的数值进行平移:
		for(int i=0;i<24;++i)
		{
			cubeVertices[i].z  -= 15;
		}
②通过模型矩阵:
                glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glLoadIdentity();//将模型矩阵清成单位矩阵

		//产生一个矩阵
		glTranslatef(0,0,-10);//单位阵与产生的矩阵相乘还是单位阵
缩放实现的两种方法:
① 通过改变模型内部的数值进行平移:
		 for (int i=0;i<sizeof(cubeVertices)/sizeof(cubeVertices[0]);++i)
		  {
			  cubeVertices[i].x *= 3;
                          cubeVertices[i].y *= 3;
			  cubeVertices[i].z *= 3;
		  }
②通过模型矩阵:
               glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵
		glTranslatef(3,0,-10);
		glScalef(1,2,1); //缩放
		glDrawArrays(GL_QUADS,0,24);
旋转实现的方法:
  通过模型矩阵:
                _angle += 0.1;
		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵 * 当前矩阵
		glTranslatef(0,0,-5);
		//产生一个矩阵
		glRotatef(_angle,1,0,0);
		glDrawArrays(GL_QUADS,0,24);
  • 矩形组合操作
                _angle += 0.1;
		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵 * 当前矩阵
		glTranslatef(0,0,-5); //平移
		glScalef(1,1.5,1);//y轴放大2倍
		glRotatef(_angle,1,0,0); //旋转
      
		glDrawArrays(GL_QUADS,0,24);
  • 运行:













                _angle += 0.1;
		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵 * 当前矩阵
		glScalef(1,1.5,1);//y轴放大2倍
		glRotatef(_angle,1,0,0); //旋转
                glTranslatef(0,0,-5); //平移

		glDrawArrays(GL_QUADS,0,24);
  • 运行:













12月12日

//lesson206.cpp

#include "glew/glew.h"
#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <math.h>

#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex //共占16个字节
{
	unsigned char r,g,b,a;//每一个占1个字节
	float x,y,z;
};

class SamplerRotate:public OpenGLWindow
{
public:
	float _angle;
public:
	SamplerRotate() 
	{
		_angle = 0;
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{255,0,0,255, -1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f, 1.0f,1.0f},
			{255,0,0,255, -1.0f, 1.0f,1.0f},

			{0,255,0,255,-1.0f,-1.0f,-1.0f},
			{0,255,0,255,-1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f,-1.0f,-1.0f},

			{0,0,255,255, -1.0f, 1.0f,  -1.0f },
			{0,0,255,255, -1.0f, 1.0f,  1.0f },
			{0,0,255,255, 1.0f, 1.0f,   1.0f },
			{0,0,255,255, 1.0f, 1.0f,   -1.0f },

			{0,255,255,255, -1.0f,-1.0f,  -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   1.0f  },
			{0,255,255,255, -1.0f,-1.0f,  1.0f  },

			{255,0,255,255,  1.0f,-1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  1.0f  },
			{255,0,255,255,  1.0f,-1.0f,  1.0f  },

			{255,255,255,255, -1.0f,-1.0f,  -1.0f },
			{255,255,255,255, -1.0f,-1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  -1.0f }
		}; 
		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		//  glLoadIdentity();//将模型矩阵清成单位矩阵

		//产生一个矩阵
		//	glTranslatef(2,2,-10);//单位阵与产生的矩阵相乘还是单位阵

#if 1
		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_C4UB_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex),cubeVertices);
#endif
		_angle += 0.1;
		glLoadIdentity();//将模型矩阵清成单位矩阵
		//产生一个矩阵 * 当前矩阵
		
		 //glScalef(1,1.5,1);//y轴放大2倍
		glTranslatef(0,0,-5); //平移
		glRotatef(_angle,1,0,0); //旋转
        
		glDrawArrays(GL_QUADS,0,24);
  //      //第2个
		//glLoadIdentity();//将模型矩阵清成单位矩阵
		//glTranslatef(3,0,-10);
	 //   glRotatef(_angle,0,1,0);
		//glDrawArrays(GL_QUADS,0,24);
  //      //第3个
		//glLoadIdentity();//将模型矩阵清成单位矩阵
		////产生一个矩阵
		//glTranslatef(3,-3,-10);
		//glRotatef(_angle,0,0,1);

		//glDrawArrays(GL_QUADS,0,24);


	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerRotate instance;
	instance.main(800,600);

	return 0;
}

12月13日

  • 太阳系(矩阵的应用-级联应用)-方式1
//lesson206.cpp

#include "glew/glew.h"
#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <math.h>

#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex //共占16个字节
{
	unsigned char r,g,b,a;//每一个占1个字节
	float x,y,z;
};

class SamplerRotate:public OpenGLWindow
{
public:
	float _angle;
    float _angleMoon; //月亮公转转速
    float _angleEarth; //月亮公转转速
public:
	SamplerRotate() 
	{
		_angle      = 0;
		_angleMoon  = 0;
		_angleEarth = 0;
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{255,0,0,255, -1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f, 1.0f,1.0f},
			{255,0,0,255, -1.0f, 1.0f,1.0f},

			{0,255,0,255,-1.0f,-1.0f,-1.0f},
			{0,255,0,255,-1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f,-1.0f,-1.0f},

			{0,0,255,255, -1.0f, 1.0f,  -1.0f },
			{0,0,255,255, -1.0f, 1.0f,  1.0f },
			{0,0,255,255, 1.0f, 1.0f,   1.0f },
			{0,0,255,255, 1.0f, 1.0f,   -1.0f },

			{0,255,255,255, -1.0f,-1.0f,  -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   1.0f  },
			{0,255,255,255, -1.0f,-1.0f,  1.0f  },

			{255,0,255,255,  1.0f,-1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  1.0f  },
			{255,0,255,255,  1.0f,-1.0f,  1.0f  },

			{255,255,255,255, -1.0f,-1.0f,  -1.0f },
			{255,255,255,255, -1.0f,-1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  -1.0f }
		}; 
		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		//  glLoadIdentity();//将模型矩阵清成单位矩阵

		//产生一个矩阵
		//	glTranslatef(2,2,-10);//单位阵与产生的矩阵相乘还是单位阵

#if 1
		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_C4UB_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex),cubeVertices);
#endif
		_angle += 0.1;
		//绘制太阳
		glLoadIdentity();
		glTranslatef(0,-10,-150); //平移
        glScalef(2,2,2);
		glRotatef(_angle,0,1,0); //旋转
		glDrawArrays(GL_QUADS,0,24);

        _angleEarth += 0.15;
		//绘制地球

		glRotatef(_angleEarth,0,1,0); //地球绕太阳转
		glTranslatef(0,0,-50); //50是地球绕太阳的半径
		glScalef(0.5,0.5,0.5);
        glRotatef(_angle,0,1,0); //旋转
        glDrawArrays(GL_QUADS,0,24);

        _angleMoon += 0.5;
		//绘制月亮
		glRotatef(_angleMoon,0,1,0); //月亮绕地球转
		glTranslatef(0,0,-10); //50是地球绕太阳的半径
		glScalef(0.5,0.5,0.5);
		glRotatef(_angle,0,1,0); //月亮自转
		glDrawArrays(GL_QUADS,0,24);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerRotate instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













  • 太阳系(矩阵的应用-级联应用)-方式2
//lesson206.cpp

#include "glew/glew.h"
#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <math.h>

#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex //共占16个字节
{
	unsigned char r,g,b,a;//每一个占1个字节
	float x,y,z;
};

class SamplerMatrix:public OpenGLWindow
{
public:
	float _angle;
    float _angleMoon; //月亮公转转速
    float _angleEarth; //月亮公转转速
public:
	SamplerMatrix() 
	{
		_angle      = 0;
		_angleMoon  = 0;
		_angleEarth = 0;
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{255,0,0,255, -1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f,-1.0f,1.0f},
			{255,0,0,255,  1.0f, 1.0f,1.0f},
			{255,0,0,255, -1.0f, 1.0f,1.0f},

			{0,255,0,255,-1.0f,-1.0f,-1.0f},
			{0,255,0,255,-1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f, 1.0f,-1.0f},
			{0,255,0,255, 1.0f,-1.0f,-1.0f},

			{0,0,255,255, -1.0f, 1.0f,  -1.0f },
			{0,0,255,255, -1.0f, 1.0f,  1.0f },
			{0,0,255,255, 1.0f, 1.0f,   1.0f },
			{0,0,255,255, 1.0f, 1.0f,   -1.0f },

			{0,255,255,255, -1.0f,-1.0f,  -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   -1.0f },
			{0,255,255,255, 1.0f,-1.0f,   1.0f  },
			{0,255,255,255, -1.0f,-1.0f,  1.0f  },

			{255,0,255,255,  1.0f,-1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  -1.0f },
			{255,0,255,255,  1.0f, 1.0f,  1.0f  },
			{255,0,255,255,  1.0f,-1.0f,  1.0f  },

			{255,255,255,255, -1.0f,-1.0f,  -1.0f },
			{255,255,255,255, -1.0f,-1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  1.0f },
			{255,255,255,255, -1.0f, 1.0f,  -1.0f }
		}; 
		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		//  glLoadIdentity();//将模型矩阵清成单位矩阵

		//产生一个矩阵
		//	glTranslatef(2,2,-10);//单位阵与产生的矩阵相乘还是单位阵

#if 1
		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_C4UB_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Vertex),cubeVertices);
#endif
		_angle += 0.1;
	//绘制太阳	
	
	CELL::matrix4 matSun;
	CELL::matrix4 matSunTrans;
	CELL::matrix4 matSunScale;
	CELL::matrix4 matSunRot;//旋转

	matSunRot.rotate(_angle,CELL::float3(0,1,0));
    matSunTrans.translate(0,-10,-150);
	matSunScale.scale(2,2,2);
    matSun  =  matSunTrans * matSunScale * matSunRot;
	glLoadMatrixf(matSun.data());
	glDrawArrays(GL_QUADS,0,24);

    //绘制地球
	CELL::matrix4 matEarth;
	CELL::matrix4 matEarTrans;
	CELL::matrix4 matEarScale;
	CELL::matrix4 matEarRot;//旋转

	matEarRot.rotate(_angleEarth,CELL::float3(0,1,0));
	matEarTrans.translate(0,0,-50);
	matEarScale.scale(0.5f,0.5f,0.5f);

	matEarth  =  matSun * matEarTrans * matEarScale * matEarRot;
	glLoadMatrixf(matEarth.data());
	_angleEarth += 0.3;
	glDrawArrays(GL_QUADS,0,24);


	_angleMoon += 1;
	//绘制月亮
	glRotatef(_angleMoon,0,1,0); //月亮绕地球转
	glTranslatef(0,0,-10); //
	glScalef(0.5,0.5,0.5);
	glRotatef(_angle,0,1,0); //月亮自转
	glDrawArrays(GL_QUADS,0,24);
}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerMatrix instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













12月14日

  • 第4章 纹理多彩世界
  • 纹理的建立
纹理映射:
纹理映射(Texture Mapping),又称纹理贴图,是将纹理空间中的纹理像素映射到屏幕空间中的像素的过程。简单来说,就是把一幅图像贴到三维物体的表面上来增强真实感,可以和光照计算、图像混合等技术结合起来形成许多非常漂亮的效果。
纹理映射











建立纹理的步骤:
①给定纹理坐标
②给定纹理
③启动纹理状态(glEnable(GL_TEXTURE_2D);)
④指定纹理坐标(glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);)
⑤绑定纹理进行绘制
//lesson206.cpp

#include "glew/glew.h"
#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <math.h>

#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{
	float u,v;
	float x,y,z;//每一个占1个字节
};

class SamplerMatrix:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int
public:

public:
	SamplerMatrix() 
	{

	}

	virtual void onInitGL()
	{
		glEnable(GL_TEXTURE_2D);
		glGenTextures(1,&_texture);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,_texture);//绑定纹理
		char* data =new char[128 * 128 * 4];
		for(int i = 0;i < 128 * 128 * 4;++ i)
		{
			data[i] = rand()%255;
		}
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,128,128,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{ 0,0,-1.0f,-1.0f,1.0f},
			{ 0,1,1.0f,-1.0f,1.0f},
			{ 1,1,1.0f, 1.0f,1.0f},
			{ 1,0,-1.0f, 1.0f,1.0f},
		}; 
		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture);//使用纹理
#if 1

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();
		glTranslatef(0,0,-10);
		glDrawArrays(GL_QUADS, 0, 4);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerMatrix instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
纹理的建立
















  • FreeImage
首先引入第三方图形库FreeImage.lib,FreeImage.h
//lesson206.cpp
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int

public:
	SamplerTexture() 
	{

	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		      FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		_texture   =   createTextureFromImage("1.PNG");
	}

	//在此实现绘制
	virtual void render()
	{
      #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{ -1.0f,-1.0f,1.0f,0,0},
			{  1.0f,-1.0f,1.0f,1,0},
			{  1.0f, 1.0f,1.0f,1,1},
			{ -1.0f, 1.0f,1.0f,0,1},
		}; 
		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
        glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();
		glTranslatef(0,0,-10);
		glDrawArrays(GL_QUADS, 0, 4);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
FreeImage


















12月15日

  • 绘制一个带贴图的正方体
//lesson206.cpp
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int

public:
	SamplerTexture() 
	{

	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		      FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		_texture   =   createTextureFromImage("1.PNG");
	}

	//在此实现绘制
	virtual void render()
	{
      #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0,0},
			{ 1.0f,-1.0f,1.0f,1,0},
			{ 1.0f, 1.0f,1.0f,1,1},
			{-1.0f, 1.0f,1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},
		};

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
        glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();
		glTranslatef(0,0,-10);

		static float angle =0;
		glRotated(angle,1,1,1);
		angle += 0.5;
		glDrawArrays(GL_QUADS, 0, 24);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:












 
贴部分图只需要修改u,v坐标:
    Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},
                }
  • 运行:
贴部分图
















12月16日

  • 一个立方体贴多图
//lesson206.cpp
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int

public:
	SamplerTexture() 
	{

	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		      FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
        char* fileName[6]=
		{
         "image/1.jpg",
		  "image/2.jpg",
		   "image/3.jpg",
		    "image/4.jpg",
			 "image/5.jpg",
			  "image/6.jpg",
		};
        for(int i=0;i<6;++i)
		{
          _texture[i] = createTextureFromImage(fileName[i]);
		}
	}
    //释放资源
	virtual void onShutdownGL()
	{
      glDeleteTextures(6,_texture);
	  int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
      #define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},
		};

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
        glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();
		glTranslatef(0,0,-10);

		static float angle =0;
		glRotated(angle,1,0,0);
		angle += 0.5;

		for(int i = 0;i < 6;++i)
		{
		   glBindTexture(GL_TEXTURE_2D,_texture[i]);
           glDrawArrays(GL_QUADS, i*4, 4);
		}
		
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
//更新OpenGLWindow.h
 virtual void onShutdownGL()
	{

	}
    virtual	bool main(int w,int h)
	{
		//2创建窗口
	HWND	hWnd  =   CreateWindowEx(
			0 // 窗口的扩展风格
			,_T("窗口标题")//需和wnd.lpszClassName一致
			,_T("窗口标题")//窗口标题
			,WS_OVERLAPPEDWINDOW//窗口风格,有无最大化最小化
			,0//窗口在屏幕的位置
			,0//窗口在屏幕的位置
			,w//宽
			,h//高
			,0//系统菜单
			,0//父窗口
			,0//实例句柄
			,this);//用户数据,用户自定义 this指当前对象
		//3更新显示
		if(hWnd)
		{
			UpdateWindow(hWnd);
			ShowWindow(hWnd,SW_SHOW);
		}
		else
		{
			return false;
		}

		if(!setup(hWnd,GetDC(hWnd)))
		{
			return false;
		}

     onInitGL();

		MSG  msg={0};
		//4消息循环
		while(WM_QUIT !=msg.message)
		{
			if(PeekMessage(&msg,0,0,0,PM_REMOVE))//有消息产生;点关闭按钮,返回值为false
			{
				TranslateMessage(&msg);//翻译
				DispatchMessage(&msg);//分发
			}
			else
			{
				RECT rect;
				GetClientRect(hWnd,&rect);
				_width  =  rect.right  -  rect.left;
				_height =  rect.bottom -  rect.top;

				glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
				glViewport(0,0,_width,_height);

				render();
				swapBuffer();
			}
		}
		onShutdownGL();
		shutdown();

		return true;
	}
  • 运行













  • 绘制多个立方体-不同贴图:
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int
	GLuint _texture1;
	GLuint _texture2;
public:
	SamplerTexture() 
	{
      glDeleteTextures(1,_texture);
	  glDeleteTextures(1,_texture1);
	  glDeleteTextures(1,_texture2);
	}

	virtual void onShutdownGL()
	{

	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	//加载纹理
	virtual void onInitGL()
	{
		_texture   =   createTextureFromImage("image/1.jpg");
		_texture1  =   createTextureFromImage("image/2.jpg");
		_texture2  =   createTextureFromImage("image/3.jpg");
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0,0},
			{ 1.0f,-1.0f,1.0f,1,0},
			{ 1.0f, 1.0f,1.0f,1,1},
			{-1.0f, 1.0f,1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},
		};

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();
		glTranslatef(0,0,-10);

		static float angle = 0;
		glRotated(angle,0,0,1);
		angle += 0.5;
		glDrawArrays(GL_QUADS, 0, 24);


		glLoadIdentity();
		glTranslatef(5,0,-10);
		glRotated(angle,0,1,0);
		glBindTexture(GL_TEXTURE_2D,_texture1);//重新绑定纹理
		glDrawArrays(GL_QUADS, 0, 24);

		glLoadIdentity();
		glTranslatef(-5,0,-10);
		glRotated(angle,1,0,0);
		glBindTexture(GL_TEXTURE_2D,_texture2);//重新绑定纹理
		glDrawArrays(GL_QUADS, 0, 24);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













12月17日

  • 纹理包装
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int
	GLuint _texture1;
	GLuint _texture2;
public:
	SamplerTexture() 
	{
      
	}

	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture);
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		//指定纹理参数
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);//s指的u方向,t指的v方向
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	//加载纹理
	virtual void onInitGL()
	{
		_texture   =   createTextureFromImage("image/1.jpg");
		_texture1  =   createTextureFromImage("image/2.jpg");
		_texture2  =   createTextureFromImage("image/3.jpg");
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0,0},
			{ 1.0f,-1.0f,1.0f,3,0},//坐标超过1,纹理重复
			{ 1.0f, 1.0f,1.0f,3,3},
			{-1.0f, 1.0f,1.0f,0,3},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},
		};

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();
		glTranslatef(0,0,-4);

		static float angle = 0;
		//glRotated(angle,0,0,1);
		angle += 0.5;
		glDrawArrays(GL_QUADS, 0, 24);

#if 0
		glLoadIdentity();
		glTranslatef(5,0,-10);
		glRotated(angle,0,1,0);
		glBindTexture(GL_TEXTURE_2D,_texture1);//重新绑定纹理
		glDrawArrays(GL_QUADS, 0, 24);

		glLoadIdentity();
		glTranslatef(-5,0,-10);
		glRotated(angle,1,0,0);
		glBindTexture(GL_TEXTURE_2D,_texture2);//重新绑定纹理
		glDrawArrays(GL_QUADS, 0, 24);
#endif
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
纹理重复















//更新
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);//GL_CLAMP参数:在T方向上延长拉伸
  • 运行:
纹理延长拉伸















//更新
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);//这个相较于GL CLAMP在边缘处有明暗变化
  • 运行:
这个相较于GL CLAMP在边缘处有明暗变化















//更新
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_MIRRORED_REPEAT);
  • 运行:
纹理镜像
















  • 纹理滤波
 *放大滤波
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int
	GLuint _texture1;
	GLuint _texture2;
public:
	SamplerTexture() 
	{
      
	}

	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture);
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		//指定纹理参数
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);


		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_MIRRORED_REPEAT);//s指的u方向,t指的v方向
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_MIRRORED_REPEAT);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	//加载纹理
	virtual void onInitGL()
	{
		_texture   =   createTextureFromImage("image/1.jpg");
		_texture1  =   createTextureFromImage("image/1.jpg");
		_texture2  =   createTextureFromImage("image/3.jpg");
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0,0},
			{ 1.0f,-1.0f,1.0f,1,0},//坐标超过1,纹理重复
			{ 1.0f, 1.0f,1.0f,1,1},
			{-1.0f, 1.0f,1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},
		};

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		//glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
		//glLoadIdentity();
		//glTranslatef(2,0,-4);

		//static float angle = 0;
		////glRotated(angle,0,0,1);
		//angle += 0.5;
		//glDrawArrays(GL_QUADS, 0, 24);

#if 1
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//线性
		glLoadIdentity();
		glTranslatef(-2,0,-4);
	//	glRotated(angle,0,1,0);
		glBindTexture(GL_TEXTURE_2D,_texture1);//重新绑定纹理
		glDrawArrays(GL_QUADS, 0, 24);

	
#endif
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:

对比来看:

GL LINEAR——较清晰
GL NEAREST——模糊









































12月18日

  • 缩小滤波
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int
	GLuint _texture1;
	GLuint _texture2;
public:
	SamplerTexture() 
	{
      
	}

	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture);
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		//指定纹理参数
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);


		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_MIRRORED_REPEAT);//s指的u方向,t指的v方向
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_MIRRORED_REPEAT);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	//加载纹理
	virtual void onInitGL()
	{
		_texture   =   createTextureFromImage("image/12.jpg");
		_texture1  =   createTextureFromImage("image/12.jpg");
		_texture2  =   createTextureFromImage("image/3.jpg");
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0,0},
			{ 1.0f,-1.0f,1.0f,1,0},//坐标超过1,纹理重复
			{ 1.0f, 1.0f,1.0f,1,1},
			{-1.0f, 1.0f,1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},
		};

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
		glLoadIdentity();
		glTranslatef(-2,0,-18);

		static float angle = 0;
		//glRotated(angle,0,0,1);
		angle += 0.5;
		glDrawArrays(GL_QUADS, 0, 24);

#if 1
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//线性
		glLoadIdentity();
		glTranslatef(2,0,-18);
	//	glRotated(angle,0,1,0);
		glBindTexture(GL_TEXTURE_2D,_texture1);//重新绑定纹理
		glDrawArrays(GL_QUADS, 0, 24);

	
#endif
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
右侧更清晰(GL_LINEAR)












  • Mipmap多层级纹理
  Mipmap的纹理过滤模式如下表:
Mipmap纹理过滤模式
 如果纹理过滤选择为GL_NEAREST或GL_LINEAR模式,那么只有基层的纹理会被加载,其他的纹理将会被忽略。
 我们必须指定其中一个mipmap过滤器,这样才能使用所有已加载的纹理。这个mipmap过滤器的常量是GL_FILTER_MIPMAP_SELECTOR的形式。其中FLILTER指定了过滤模式,SELECTOR指定了如何选择mipmap层。
 例如GL_NEAREST_MIPMAP_LINEAR模式,它的SELECTOR是GL_LINEAR,它会在两个最邻近的mip层中执行线性插值,然后得出的结果又由被选择的过滤器GL_NEAREST进行过滤。
     GL_NEAREST_MIPMAP_NEAREST模式,具有很好的性能,也能够解决闪烁的问题,但在视觉效果上会比较差。
     GL_LINEAR_MIPMAP_NEAREST模式,常用于游戏加速,使用了质量较高的线性过滤,和快速的选择的方式(最邻近方式)。
     GL_LINEAR_MIPMAP_LINEAR和GL_NEAREST_MIPMAP_LINEAR过滤器在mip层之间执行一些额外的线性插值,以消除不同层之间的变换痕迹,但也需要一些额外的性能开销。
     GL_LINEAR_MIPMAP_LINEAR具有最高的精度


邻近过滤(Nearest Neighbor Filtering) 左上角那个纹理像素的中心距离纹理坐标最近,所以它会被选择为样本颜色:

邻近过滤













线性过滤(linear Filtering) 它会基于纹理坐标附近的纹理像素,计算出一个插值,近似出这些纹理像素之间的颜色。

线性过滤
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <gl/GLU.h>
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int
	GLuint _texture1;
	GLuint _texture2;
public:
	SamplerTexture() 
	{

	}

	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture);
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		//指定纹理参数
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_MIRRORED_REPEAT);//s指的u方向,t指的v方向
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_MIRRORED_REPEAT);
		//给纹理指定数据
		//glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,w,h,GL_RGBA,GL_UNSIGNED_BYTE,data);

		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);//0层作为基础图层
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,4);//最大层为4层
		
		return texId;

		

	}
	//加载纹理
	virtual void onInitGL()
	{
		_texture   =   createTextureFromImage("image/12.jpg");
		_texture1  =   createTextureFromImage("image/12.jpg");
		_texture2  =   createTextureFromImage("image/3.jpg");
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0,0},
			{ 1.0f,-1.0f,1.0f,1,0},//坐标超过1,纹理重复
			{ 1.0f, 1.0f,1.0f,1,1},
			{-1.0f, 1.0f,1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},
		};

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		//左边
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST);
		glLoadIdentity();
		glTranslatef(-4,0,-8);

		static float angle = 0;
		//glRotated(angle,0,0,1);
		angle += 0.5;
		glDrawArrays(GL_QUADS, 0, 24);

#if 1
		//右边
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);//线性
		glLoadIdentity();
		glTranslatef(4,0,-8);
		//	glBindTexture(GL_TEXTURE_2D,_texture1);//重新绑定纹理
		glDrawArrays(GL_QUADS, 0, 24);


#endif
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
Mipmap多层级
















12月21日

  • Mipmap巩固
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <gl/GLU.h>
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{
	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int
public:
	SamplerTexture() 
	{

	}

	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture);
	}
 
	virtual FIBITMAP*readImage(const char* fileName)
	{
		//1 获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
        //2 加载图片
        FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
        FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);
	    //3 获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width  = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		 //默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
	     BYTE temp      = pixels[i];
		 pixels[i]      = pixels[i + 2];
		 pixels[i + 2]  =temp;
		 }
		 return dib;
	}

	//加载纹理
	virtual void onInitGL()
	{
		FIBITMAP*   arrayImage[6];
		arrayImage[0] = readImage("tex256.bmp");
		arrayImage[1] = readImage("tex128.bmp");
		arrayImage[2] = readImage("tex64.bmp");
		arrayImage[3] = readImage("tex32.bmp");
		arrayImage[4] = readImage("tex16.bmp");
		arrayImage[5] = readImage("tex8.bmp");
    
		//建一个纹理
		glGenTextures(1,&_texture);
		glBindTexture(GL_TEXTURE_2D,_texture);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		 //没有产生的数据默认是白的
		{
			//加载一个纹理
         FIBITMAP* base   = readImage("texbase256.bmp");
		 BYTE*     pixels = (BYTE*)FreeImage_GetBits(base);
		 int       width  =  FreeImage_GetWidth(base);
		 int       height =  FreeImage_GetHeight(base);
		  //产生一个Mipmap纹理
		 gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,width,height,GL_RGBA,GL_UNSIGNED_BYTE,pixels);
		}
        //更改Mipmap里的数据
		for(int i = 0;i < 6; ++i)
		{
			BYTE* pixels = (BYTE*)FreeImage_GetBits(arrayImage[i]);
			int   width  =  FreeImage_GetWidth(arrayImage[i]);
			int   height =  FreeImage_GetHeight(arrayImage[i]);
			glTexImage2D(GL_TEXTURE_2D,i,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixels);
			FreeImage_Unload(arrayImage[i]); //释放
		}
	}

	//在此实现绘制
	virtual void    render()
	{
		//! 指定以下的操作针对投影矩阵
		glMatrixMode(GL_PROJECTION);
		//! 将投影举证清空成单位矩阵
		glLoadIdentity();

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
		
		float size  =  5;
		Vertex cubeVertices[] =
		{
			{-size,0,-size, 0, 0},
			{-size,0, size, 1, 0},
			{ size,0, size, 1, 1},
			{ size,0,-size, 0, 1},
		};
		glMatrixMode(GL_MODELVIEW);
		glBindTexture(GL_TEXTURE_2D,_texture);

		glEnable(GL_DEPTH_TEST);
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);


		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_NEAREST);
		//! 清成单位矩阵
		glLoadIdentity();
		//! 产生一个矩阵
		glTranslatef(0,-1,-8);

		glDrawArrays( GL_QUADS, 0, 4 );

	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
GL NEAREST MIPMAP NEAREST















glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST_MIPMAP_LINEAR);
GL_NEAREST_MIPMAP_LINEAR















glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
GL_LINEAR_MIPMAP_LINEAR
















  • 纹理的更新——局部更新-以及替换(高效率)
//纹理局部更新
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <gl/GLU.h>
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{
	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int
public:
	SamplerTexture() 
	{

	}

	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture);
	}
 
	virtual FIBITMAP*readImage(const char* fileName)
	{
		//1 获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
        //2 加载图片
        FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
        FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);
	    //3 获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width  = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		 //默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
	     BYTE temp      = pixels[i];
		 pixels[i]      = pixels[i + 2];
		 pixels[i + 2]  =temp;
		 }
		 return dib;
	}

	//加载纹理
	virtual void onInitGL()
	{
		FIBITMAP*   arrayImage[6];
		arrayImage[0] = readImage("tex256.bmp");
		arrayImage[1] = readImage("tex128.bmp");
		arrayImage[2] = readImage("tex64.bmp");
		arrayImage[3] = readImage("tex32.bmp");
		arrayImage[4] = readImage("tex16.bmp");
		arrayImage[5] = readImage("tex8.bmp");
    
		//建一个纹理
		glGenTextures(1,&_texture);
		glBindTexture(GL_TEXTURE_2D,_texture);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);

		 //没有产生的数据默认是白的
	
		BYTE* pixels = (BYTE*)FreeImage_GetBits(arrayImage[0]);
		int   width  =  FreeImage_GetWidth(arrayImage[0]);
		int   height =  FreeImage_GetHeight(arrayImage[0]);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixels);
		FreeImage_Unload(arrayImage[0]); //释放

		{
			BYTE* pixels = (BYTE*)FreeImage_GetBits(arrayImage[2]);
			int   width  =  FreeImage_GetWidth(arrayImage[2]);
			int   height =  FreeImage_GetHeight(arrayImage[2]);
			//更新纹理
			glTexSubImage2D(GL_TEXTURE_2D,0,100,100,width,height,GL_RGBA,GL_UNSIGNED_BYTE,pixels);
		}
	}

	//在此实现绘制
	virtual void    render()
	{
		//! 指定以下的操作针对投影矩阵
		glMatrixMode(GL_PROJECTION);
		//! 将投影举证清空成单位矩阵
		glLoadIdentity();

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
		
		Vertex cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f    ,0,  0 },
			{  1.0f,-1.0f, 1.0f    ,1,  0 },
			{  1.0f, 1.0f, 1.0f    ,1,  1 },
			{ -1.0f, 1.0f, 1.0f    ,0,  1 },
		};
		glMatrixMode(GL_MODELVIEW);
		glBindTexture(GL_TEXTURE_2D,_texture);

		glEnable(GL_DEPTH_TEST);
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

		glBindTexture(GL_TEXTURE_2D,_texture);//绑定纹理

		//! 清成单位矩阵
		glLoadIdentity();
		//! 产生一个矩阵
		glTranslatef(0,0,-4);

		glDrawArrays( GL_QUADS, 0, 4 );

	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
纹理局部更新
















12月22日

  • 纹理动画-滚动的广告牌
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <gl/GLU.h>
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{
	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int

	float  _textureV;
public:
	SamplerTexture() 
	{
        _textureV = 0;
	}

	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture);
	}
 
	virtual FIBITMAP*readImage(const char* fileName)
	{
		//1 获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
        //2 加载图片
        FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
        FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);
	    //3 获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width  = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		 //默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
	     BYTE temp      = pixels[i];
		 pixels[i]      = pixels[i + 2];
		 pixels[i + 2]  =temp;
		 }
		 return dib;
	}

	//加载纹理
	virtual void onInitGL()
	{
		FIBITMAP*   arrayImage[1];
		arrayImage[0] = readImage("1.png");
		
    
		//建一个纹理
		glGenTextures(1,&_texture);
		glBindTexture(GL_TEXTURE_2D,_texture);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

		 //没有产生的数据默认是白的
	
		BYTE* pixels = (BYTE*)FreeImage_GetBits(arrayImage[0]);
		int   width  =  FreeImage_GetWidth(arrayImage[0]);
		int   height =  FreeImage_GetHeight(arrayImage[0]);
		//实际的分配显存,删掉原来的显存纹理,建立新的显存纹理
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixels);
		FreeImage_Unload(arrayImage[0]); //释放

	}

	//在此实现绘制
	virtual void    render()
	{
		//! 指定以下的操作针对投影矩阵
		glMatrixMode(GL_PROJECTION);
		//! 将投影举证清空成单位矩阵
		glLoadIdentity();

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
		
		_textureV += 0.001f;
		Vertex cubeVertices[] =
		{
			{ -1.0f,-0.125f, 1.0f    ,0,  0 },
			{  1.0f,-0.125f, 1.0f    ,1,  0 },
			{  1.0f, 0.125f, 1.0f    ,1,  0.25f },
			{ -1.0f, 0.125f, 1.0f    ,0,  0.25f },
		};

		for(int i = 0 ; i < 4; ++i)
		{
             cubeVertices[i].v += _textureV;
		}
		glMatrixMode(GL_MODELVIEW);
		glBindTexture(GL_TEXTURE_2D,_texture);

		glEnable(GL_DEPTH_TEST);
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

		glBindTexture(GL_TEXTURE_2D,_texture);//绑定纹理

		//! 清成单位矩阵
		glLoadIdentity();
		//! 产生一个矩阵
		glTranslatef(0,0,-4);

		glDrawArrays( GL_QUADS, 0, 4 );

	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:















  • 纹理矩阵变换-纹理动画
GLES中没有纹理矩阵,所以只可以在PC端使用,移动端不行
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <gl/GLU.h>
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{
	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int

	float  _textureV;
public:
	SamplerTexture() 
	{
        _textureV = 0;
	}

	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture);
	}
 
	virtual FIBITMAP*readImage(const char* fileName)
	{
		//1 获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
        //2 加载图片
        FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
        FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);
	    //3 获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width  = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		 //默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
	     BYTE temp      = pixels[i];
		 pixels[i]      = pixels[i + 2];
		 pixels[i + 2]  =temp;
		 }
		 return dib;
	}

	//加载纹理
	virtual void onInitGL()
	{
		FIBITMAP*   arrayImage[1];
		arrayImage[0] = readImage("1.png");
		
    
		//建一个纹理
		glGenTextures(1,&_texture);
		glBindTexture(GL_TEXTURE_2D,_texture);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

		 //没有产生的数据默认是白的
	
		BYTE* pixels = (BYTE*)FreeImage_GetBits(arrayImage[0]);
		int   width  =  FreeImage_GetWidth(arrayImage[0]);
		int   height =  FreeImage_GetHeight(arrayImage[0]);
		//实际的分配显存,删掉原来的显存纹理,建立新的显存纹理
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,pixels);
		FreeImage_Unload(arrayImage[0]); //释放

	}

	//在此实现绘制
	virtual void    render()
	{
		//! 指定以下的操作针对投影矩阵
		glMatrixMode(GL_PROJECTION);
		//! 将投影举证清空成单位矩阵
		glLoadIdentity();

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
		
		Vertex cubeVertices[] =
		{
			{ -1.0f,-0.125f, 1.0f    ,0,  0 },
			{  1.0f,-0.125f, 1.0f    ,1,  0 },
			{  1.0f, 0.125f, 1.0f    ,1,  0.25f },
			{ -1.0f, 0.125f, 1.0f    ,0,  0.25f },
		};

	    glMatrixMode(GL_TEXTURE);//默认纹理矩阵是单位阵
		//glTranslatef(0.001f,0,0);//当前矩阵与单位阵做累加
        //glLoadIdentity();
		//glScalef(4,4,4);
		glRotatef(0.1,0,0,1);
		glMatrixMode(GL_MODELVIEW);
		glBindTexture(GL_TEXTURE_2D,_texture);

		glEnable(GL_DEPTH_TEST);
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

		glBindTexture(GL_TEXTURE_2D,_texture);//绑定纹理

		//! 清成单位矩阵
		glLoadIdentity();
		//! 产生一个矩阵
		glTranslatef(0,0,-4);

		glDrawArrays( GL_QUADS, 0, 4 );

	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













12月23日

  • MultiTexture多纹理
多纹理:OpenGL默认一个三角面上至少贴8张纹理
总结:
   glMatrixMode()函数:对接下来要做什么进行一下声明,也就是在要做下一步之前告诉计算机要进行什么操作。
   参数有:GL_PROJECTION,GL_MODELVIEW和GL_TEXTURE;
   ①GL_PROJECTION:要对投影相关进行操作,也就是把物体投影到一个平面上,把3维物体投到2维的平面上;
   ②GL_MODELVIEW:是对模型视景的操作,接下来的语句描绘一个以模型为基础的适应;
   ③GL_TEXTURE:是对纹理相关进行操作;
   规范一点来说,glMatrixMode是用来指定哪一个矩阵是当前矩阵,而它的参数代表要操作的目标,GL_PROJECTION是对投影矩阵操作,GL_MODELVIEW是对模型视景矩阵操作,GL_TEXTURE是对纹理矩阵进行随后的操作。
   void glLoadIdentity(void);——恢复初始坐标系的手段,其功能是用一个4×4的单位矩阵来替换当前矩阵,实际上就是对当前矩阵进行初始化。
   当调用glLoadIdentity()之后,您实际上将当前点移到了屏幕中心:
#include <windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <gl/GLU.h>
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture1;//纹理句柄;数字,无符号int
	GLuint _texture2;

	float  _textureV;
public:
	SamplerTexture() 
	{
		_textureV = 0;
	}

	virtual void onInitGL()
	{
		_texture1   =   createTextureFromImage("Bitmap.bmp");
		_texture2   =   createTextureFromImage("Lightmap.bmp");
	}
	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}


	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
#if 1
		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glLoadIdentity();
		glTranslatef(0,0,-4);

		glActiveTextureARB(GL_TEXTURE0_ARB);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texture1);//使用纹理

		glActiveTextureARB(GL_TEXTURE1_ARB);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texture2);

		glBegin(GL_QUADS);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0.0f,1.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0.0f,1.0f);

		glVertex3f(-1, 1,0);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0.0f,0.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0.0f,0.0f);

		glVertex3f(-1,-1,0);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,1.0f,0.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1.0f,0.0f);

		glVertex3f( 1,-1,0);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,1.0f,1.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1.0f,1.0f);

		glVertex3f( 1, 1,0);

		glEnd();



#else 
		glEnable(GL_DEPTH_TEST);//深度测试


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
	}
};

//CALLBACK 标准调用 等价于_stdcall
int __stdcall WinMain(
					  HINSTANCE hInstance,
					  HINSTANCE hPrevInstance,
					  LPSTR lpCmdLine,
					  int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
多纹理
















更高效的方式--顶点数组方式

#include <windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <gl/GLU.h>

#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture1;//纹理句柄;数字,无符号int
	GLuint _texture2;

	float  _textureV;
public:
	SamplerTexture() 
	{
		_textureV = 0;
	}

	virtual void onInitGL()
	{
		_texture1   =   createTextureFromImage("Cove.bmp");
		_texture2   =   createTextureFromImage("fog.bmp");
	}
	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}


	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
#if 0
		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glLoadIdentity();
		glTranslatef(0,0,-4);

		glActiveTextureARB(GL_TEXTURE0_ARB);//激活纹理单元
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texture1);//使用纹理

		glActiveTextureARB(GL_TEXTURE1_ARB);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texture2);

		glBegin(GL_QUADS);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0.0f,1.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0.0f,1.0f);

		glVertex3f(-1, 1,0);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0.0f,0.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0.0f,0.0f);

		glVertex3f(-1,-1,0);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,1.0f,0.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1.0f,0.0f);

		glVertex3f( 1,-1,0);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,1.0f,1.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1.0f,1.0f);

		glVertex3f( 1, 1,0);

		glEnd();



#else //顶点数组方式,更高效
		Vertex cubeVertices[] = 
		{
			{-1.0f,-1,1.0f,0,0},
		    { 1.0f,-1,1.0f,1,0},
			{ 1.0f, 1,1.0f,1,1},
		    {-1.0f, 1,1.0f,0,1},
		};
		glActiveTextureARB(GL_TEXTURE0_ARB);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texture1);

		glActiveTextureARB(GL_TEXTURE1_ARB);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texture2);

		glMatrixMode(GL_MODELVIEW);
        //启用三维顶点
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
        //启用纹理数组
		glClientActiveTextureARB(GL_TEXTURE0_ARB);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glClientActiveTextureARB(GL_TEXTURE1_ARB);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].v);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glLoadIdentity();
		glTranslatef(0,0,-4);
		glDrawArrays(GL_QUADS,0,4);

#endif
	}
};

//CALLBACK 标准调用 等价于_stdcall
int __stdcall WinMain(
					  HINSTANCE hInstance,
					  HINSTANCE hPrevInstance,
					  LPSTR lpCmdLine,
					  int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:
多纹理--顶点数组方式
















12月24日

  • 多纹理应用-漂浮的云
#include <windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <gl/GLU.h>

#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
    float u1,v1;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture1;//纹理句柄;数字,无符号int
	GLuint _texture2;

	float  _textureV; //控制纹理动
public:
	SamplerTexture() 
	{
		_textureV = 0;
	}

	virtual void onInitGL()
	{
		_texture1   =   createTextureFromImage("Cove.bmp");
		_texture2   =   createTextureFromImage("fog.bmp");
	}
	virtual void onShutdownGL()
	{
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}


	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);
#if 0
		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glLoadIdentity();
		glTranslatef(0,0,-4);

		glActiveTextureARB(GL_TEXTURE0_ARB);//激活纹理单元
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texture1);//使用纹理

		glActiveTextureARB(GL_TEXTURE1_ARB);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texture2);

		glBegin(GL_QUADS);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0.0f,1.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0.0f,1.0f);

		glVertex3f(-1, 1,0);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,0.0f,0.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,0.0f,0.0f);

		glVertex3f(-1,-1,0);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,1.0f,0.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1.0f,0.0f);

		glVertex3f( 1,-1,0);

		glMultiTexCoord2fARB(GL_TEXTURE0_ARB,1.0f,1.0f);
		glMultiTexCoord2fARB(GL_TEXTURE1_ARB,1.0f,1.0f);

		glVertex3f( 1, 1,0);

		glEnd();



#else //顶点数组方式,更高效
		Vertex cubeVertices[] = 
		{
			{-1.0f,-1,1.0f,0,0,0,0},
		    { 1.0f,-1,1.0f,1,0,1,0},
			{ 1.0f, 1,1.0f,1,1,1,1},
		    {-1.0f, 1,1.0f,0,1,0,1},
		};
        //方法1
        glMatrixMode(GL_TEXTURE);
		glTranslatef(0.0005f,0,0);

		_textureV += 0.0005f;
		//方法2
		/*for(int i = 0;i < 4;++i)
		{
			cubeVertices[i].u1 +=_textureV;
		}*/
		glActiveTextureARB(GL_TEXTURE0_ARB);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texture1);

		glActiveTextureARB(GL_TEXTURE1_ARB);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texture2);

		glMatrixMode(GL_MODELVIEW);
        //启用三维顶点
		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
        //启用纹理数组
		glClientActiveTextureARB(GL_TEXTURE0_ARB);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glClientActiveTextureARB(GL_TEXTURE1_ARB);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u1);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glLoadIdentity();
		glTranslatef(0,0,-4);
		glDrawArrays(GL_QUADS,0,4);

#endif
	}
};

//CALLBACK 标准调用 等价于_stdcall
int __stdcall WinMain(
					  HINSTANCE hInstance,
					  HINSTANCE hPrevInstance,
					  LPSTR lpCmdLine,
					  int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













  • 压缩纹理:(提升绘制的效率和性能)
  常见的纹理格式-ETC1:
基于OpenGL ES的压缩纹理有常见的如下几种实现:
  1)ETC1(Ericsson texture compression)
  2)PVRTC (PowerVR texture compression)
  3)ATITC (ATI texture compression)
  4)S3TC (S3 texture compression)
<br>
ETC1:
  ETC1格式是OpenGL ES图形标准的一部分,并且被所有的Android设备所支持。
  扩展名为: GL_OES_compressed_ETC1_RGB8_texture,不支持透明通道,所以仅能用于不透明纹理。
当加载压缩纹理时,参数支持如下格式:GL_ETC1_RGB8_OES(RGB,每个像素0.5个字节)
<br>
PowerVR:(目前苹果手机用的所有图形芯片都是该厂商提供,性能强悍)
  支持的GPU为Imagination Technologies的PowerVR SGX系列。
  OpenGL ES的扩展名为: GL_IMG_texture_compression_pvrtc。
当加载压缩纹理时,参数支持如下几种格式:
   GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG (RGB,每个像素0.5个字节)
   GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG (RGB,每个像素0.25个字节)
   GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG (RGBA,每个像素0.5个字节)
   GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG (RGBA,每个像素0.25个字节)
<br>
ATITC:()
   支持的GPU为Qualcomm的Adreno系列。
   支持的OpenGL ES扩展名为: GL_ATI_texture_compression_atitc。
当加载压缩纹理时,参数支持如下类型的纹理:
   GL_ATC_RGB_AMD (RGB,每个像素0.5个字节)
   GL_ATC_RGBA_EXPLICIT_ALPHA_AMD (RGBA,每个像素1个字节)
   GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD (RGBA,每个像素1个字节)
S3TC:
   也被称为DXTC,在PC上广泛被使用,但是在移动设备上还是属于新鲜事物。支持的GPU为NVIDIA Tegra系列。
   OpenGL ES扩展名为:GL_EXT_texture_compression_dxt1和GL_EXT_texture_compression_s3tc。
当加载压缩纹理时,参数有如下几种格式:
   GL_COMPRESSED_RGB_S3TC_DXT1 (RGB,每个像素0.5个字节)
   GL_COMPRESSED_RGBA_S3TC_DXT1 (RGBA,每个像素0.5个字节)
   GL_COMPRESSED_RGBA_S3TC_DXT3 (RGBA,每个像素1个字节)
   GL_COMPRESSED_RGBA_S3TC_DXT5 (RGBA,每个像素1个字节)
纹理格式的查询:
如何获取GPU支持哪些压缩纹理
string extensions = (const char*)glGetString(GL_EXTENSIONS);
a. 判断是否支持ETC1格式的压缩纹理
return (extensions.find("GL_OES_compressed_ETC1_RGB8_texture")!= string::npos);
b. 判断是否支持DXT格式的压缩纹理
return (extensions.find("GL_EXT_texture_compression_dxt1")!= string::npos || extensions.find("GL_EXT_texture_compression_s3tc")!= string::npos);
c. 判断是否支持PVRTC格式的压缩纹理
return (extensions.find("GL_IMG_texture_compression_pvrtc")!= string::npos);
d. 判断是否支持ATITC格式的压缩纹理
return (extensions.find("GL_AMD_compressed_ATC_texture")!= string::npos || extensions.find("GL_ATI_texture_compression_atitc")!= string::npos);
virtual void onInitGL()
	{
		_texture1   =   createTextureFromImage("Cove.bmp");
		_texture2   =   createTextureFromImage("fog.bmp");
		std::string extensions = (const char*)glGetString(GL_EXTENSIONS);
		bool has = extensions.find("GL_EXT_texture_compression_s3tc")!= std::string::npos;
	}
  • 结果:
压缩纹理—调试








12月25日

  • dds压缩纹理的加载
#include <windows.h>
#include <tchar.h>
#include <math.h>
#include <ddraw.h>
#include <string>

#include "FreeImage.h"


#include "CELLMath.hpp"

#include "OpenGLWindow.h"
#include <gl/GLU.h>
#include <vector>
using namespace CELL;

struct Vertex
{ 
    
    float x, y, z;
    float u, v;
};
struct DDS_IMAGE_DATA
{
    GLsizei  width;
    GLsizei  height;
    GLint    components;
    GLenum   format;
    int      numMipMaps;
    GLubyte *pixels;
};
class   SamplerTexture :public OpenGLWindow
{
    GLuint  _texture1;
    GLuint  _texture2;


    float   _textureV;
public:
    SamplerTexture() 
    {
        _textureV   =   0;
    }

    virtual void    onInitGL()
    {
        _texture1   =   createTextureFromDDS("1.dds");
    }

    virtual void    onShutdownGL()
    {
        glDeleteTextures(1,&_texture1);
    }

    unsigned    createTextureFromDDS(const char* filename)
    {
        DDS_IMAGE_DATA* data    =   loadDDSTextureFile(filename);
        unsigned        res     =   createDxtTexture(data);
        if( data != NULL )
        {
            if( data->pixels != NULL )
                free( data->pixels );

            free( data );
        }
        return  res;

    }

    DDS_IMAGE_DATA* loadDDSTextureFile( const char *filename )
    {
        DDS_IMAGE_DATA *pDDSImageData;
        DDSURFACEDESC2 ddsd;
        char filecode[4];
        FILE *pFile;
        int factor;
        int bufferSize;

        // Open the file
        pFile = fopen( filename, "rb" );

        if( pFile == NULL )
        {
            char str[255];
            return NULL;
        }

        fread( filecode, 1, 4, pFile );

        if( strncmp( filecode, "DDS ", 4 ) != 0 )
        {
            char str[255];
            fclose( pFile );
            return NULL;
        }

        fread( &ddsd, sizeof(ddsd), 1, pFile );

        pDDSImageData = (DDS_IMAGE_DATA*) malloc(sizeof(DDS_IMAGE_DATA));

        memset( pDDSImageData, 0, sizeof(DDS_IMAGE_DATA) );

        switch( ddsd.ddpfPixelFormat.dwFourCC )
        {
        case FOURCC_DXT1:
            // DXT1's compression ratio is 8:1
            pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
            factor = 2;
            break;

        case FOURCC_DXT3:
            // DXT3's compression ratio is 4:1
            pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
            factor = 4;
            break;

        case FOURCC_DXT5:
            // DXT5's compression ratio is 4:1
            pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
            factor = 4;
            break;

        default:
            return NULL;
        }

        if( ddsd.dwLinearSize == 0 )
        {
            return  0;
        }

        if( ddsd.dwMipMapCount > 1 )
            bufferSize = ddsd.dwLinearSize * factor;
        else
            bufferSize = ddsd.dwLinearSize;

        pDDSImageData->pixels = (unsigned char*)malloc(bufferSize * sizeof(unsigned char));

        fread( pDDSImageData->pixels, 1, bufferSize, pFile );

        fclose( pFile );

        pDDSImageData->width      = ddsd.dwWidth;
        pDDSImageData->height     = ddsd.dwHeight;
        pDDSImageData->numMipMaps = ddsd.dwMipMapCount;

        if( ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT1 )
            pDDSImageData->components = 3;
        else
            pDDSImageData->components = 4;

        return pDDSImageData;
    }


    unsigned        createDxtTexture(DDS_IMAGE_DATA* pDDSImageData)
    {
        if( pDDSImageData != NULL )
        {
            int nHeight     = pDDSImageData->height;
            int nWidth      = pDDSImageData->width;
            int nNumMipMaps = pDDSImageData->numMipMaps;

            int nBlockSize;

            if( pDDSImageData->format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT )
                nBlockSize = 8;
            else
                nBlockSize = 16;

            unsigned    textureId;

            glGenTextures( 1, &textureId );
            glBindTexture( GL_TEXTURE_2D, textureId );

            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

            int nSize;
            int nOffset = 0;

            // Load the mip-map levels

            for( int i = 0; i < nNumMipMaps; ++i )
            {
                if( nWidth  == 0 ) nWidth  = 1;
                if( nHeight == 0 ) nHeight = 1;

                nSize = ((nWidth+3)/4) * ((nHeight+3)/4) * nBlockSize;

                glCompressedTexImage2DARB( GL_TEXTURE_2D,
                    i,
                    pDDSImageData->format,
                    nWidth,
                    nHeight,
                    0,
                    nSize,
                    pDDSImageData->pixels + nOffset );

                nOffset += nSize;

                nWidth  = (nWidth  / 2);
                nHeight = (nHeight / 2);
            }
            return  textureId;
        }
        return  0;
        
    }

     /**
    *   使用FreeImage加载图片
    */
    unsigned    createTextureFromImage(const char* fileName)
    {
        //1 获取图片格式
        FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
        if (fifmt == FIF_UNKNOWN)
        {
            return  0;
        }
        //2 加载图片
        FIBITMAP    *dib = FreeImage_Load(fifmt, fileName,0);
     
        FREE_IMAGE_COLOR_TYPE type    =   FreeImage_GetColorType(dib);
      
        //! 获取数据指针
        FIBITMAP*   temp    =   dib;
        dib =   FreeImage_ConvertTo32Bits(dib);
                FreeImage_Unload(temp);

        BYTE*   pixels =   (BYTE*)FreeImage_GetBits(dib);
        int     width   =   FreeImage_GetWidth(dib);
        int     height  =   FreeImage_GetHeight(dib);

        for (int i = 0 ;i < width * height * 4 ; i+=4 )
        {
            BYTE temp       =   pixels[i];
            pixels[i]       =   pixels[i + 2];
            pixels[i + 2]   =   temp;
        }

        unsigned    res =   createTexture(width,height,pixels);
        FreeImage_Unload(dib);
        return      res;
    }

    unsigned    createTexture(int w,int h,const void* data)
    {
        unsigned    texId;
        glGenTextures(1,&texId);
        glBindTexture(GL_TEXTURE_2D,texId);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_MIRRORED_REPEAT);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
       
        glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);

       
        return  texId;
    }
   
    virtual void    render()
    {
#define M_PI (3.14159265358979323846)
        //! 指定以下的操作针对投影矩阵
        glMatrixMode(GL_PROJECTION);
        //! 将投影举证清空成单位矩阵
        glLoadIdentity();

        gluPerspective(60,double(_width)/double(_height),0.1,1000);

        Vertex cubeVertices[] =
        {
            {  -1.0f,-1, 1.0f    ,0,  0},
            {  1.0f,-1, 1.0f     ,1,  0},
            {  1.0f, 1, 1.0f     ,1,  1},
            { -1.0f, 1, 1.0f     ,0,  1},
        };
     

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,  _texture1);

     
        glMatrixMode(GL_MODELVIEW);
        
        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(Vertex),     &cubeVertices[0].x);

        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(2,GL_FLOAT,       sizeof(Vertex),     &cubeVertices[0].u);
        //! 清成单位矩阵
        glLoadIdentity();
        //! 产生一个矩阵
        glTranslatef(0,0,-4);
        glDrawArrays( GL_QUADS, 0, 4 );
    }
};
int __stdcall WinMain( 
                      HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, 
                      int nShowCmd
                      )
{
    SamplerTexture    instance;
    instance.main(800,600);
    return  0;
}
  • 运行:
dds压缩纹理的加载
















  • 环境纹理
#include <windows.h>
#include <tchar.h>
#include <math.h>
#include <ddraw.h>
#include <string>

#include "FreeImage.h"


#include "CELLMath.hpp"

#include "OpenGLWindow.h"
#include <gl/GLU.h>
#include <vector>
using namespace CELL;

struct Vertex
{ 
    
    float x, y, z;
    float u, v;
};
struct DDS_IMAGE_DATA
{
    GLsizei  width;
    GLsizei  height;
    GLint    components;
    GLenum   format;
    int      numMipMaps;
    GLubyte *pixels;
};
class   SamplerTexture :public OpenGLWindow
{
    GLuint         _texture1;
    GLUquadricObj  *quadratic;

public:
    SamplerTexture() 
    {

    }

    virtual void    onInitGL()
    {
        _texture1   =   createTextureFromImage("BG.bmp");
		quadratic   =   gluNewQuadric();
		gluQuadricNormals(quadratic,GLU_SMOOTH);//产生法线
		gluQuadricTexture(quadratic,GL_TRUE);//产生纹理坐标
        
		glEnable(GL_TEXTURE_GEN_S);
        glEnable(GL_TEXTURE_GEN_T);//启用纹理环境
		//指定纹理环境的参数
		glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);//GL_SPHERE_MAP球形映射
        glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
	
	}

    virtual void    onShutdownGL()
    {
        glDeleteTextures(1,&_texture1);
    }

	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
   
    virtual void    render()
    {
#define M_PI (3.14159265358979323846)
        //! 指定以下的操作针对投影矩阵
        glMatrixMode(GL_PROJECTION);
        //! 将投影举证清空成单位矩阵
        glLoadIdentity();

        gluPerspective(60,double(_width)/double(_height),0.1,1000);

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,  _texture1);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0,0,-5);

		gluSphere(quadratic,1.3f,32,32);
 
    }
};

int __stdcall WinMain( 
                      HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, 
                      int nShowCmd
                      )
{

    SamplerTexture    instance;
    instance.main(800,600);


    return  0;
}
  • 运行:
环境纹理
















12月29日

  • 帧动画
glOrtho是创建一个正交平行的视景体。这个函数简单理解起来,就是一个物体摆在那里,你怎么去截取他。
GlOrtho()
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h"
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"

#include "CELLImageReader.hpp"

#include <vector>
using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
    float x, y, z;
    float u, v;
};

class   SamplerTexture :public OpenGLWindow
{
public:
    GLuint         _texture1;
    int            _texWidth;
	int            _texHeight;

	int            _imageWidth;
	int            _imageHeight;

public:
		/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}

	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		_texWidth   =  width;
		_texHeight  =  height;
		_imageWidth =  108;
		_imageHeight =  108;//一张小图片的

		////默认情况下加载来的数据是bgra
		//for(int i = 0;i<width * height * 4 ;i += 4)
		//{
		//	BYTE temp      = pixels[i];
		//	pixels[i]      = pixels[i + 2];
		//	pixels[i + 2]  =temp;
		//}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

    virtual void    onInitGL()
    {
		glClearColor(0.0f,0.0f,0.0f,1.0f);
        glEnable(GL_TEXTURE_2D);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
        _texture1   =   createTextureFromImage("xx.png");
	}

    virtual void    onShutdownGL()
    {
        glDeleteTextures(1,&_texture1);
    }
	void  renderOrth(float fFrame) //传的帧数
	{
         glMatrixMode(GL_PROJECTION);
		 glLoadIdentity();
		 glOrtho(0,_width,_height,0,-100,100); //正交投影

		 int _col = 9;//列

		 int   frame = (int)fFrame;
		 int   col   = frame%_col;
		 int   row   = frame / _col;
         //计算小图片的纹理坐标(左下角uv坐标)
		 float u  = float(_imageWidth * col) /float(_texWidth);
		 float v  = float(_imageHeight * row) /float(_texHeight);
         //(右上角uv坐标)
		 float u1  = float(_imageWidth * (col + 1)) /float(_texWidth);
		 float v1  = float(_imageHeight * (row + 1)) /float(_texHeight);

         int   w =  108;
		 int   h =  108;

		 Vertex vert[] =
		 {
			 {0,0,0,u, v1},
			 {0,h,0,u, v},
			 {w,h,0,u1,v},
			 {w,0,0,u1,v1},
		 };
         glBindTexture(GL_TEXTURE_2D,_texture1); //绑定纹理

		 glEnableClientState(GL_VERTEX_ARRAY);//启用顶点状态
		 glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&vert[0].x);//启用顶点缓冲区

		 glEnableClientState(GL_TEXTURE_COORD_ARRAY);//启用纹理数组状态
		 glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&vert[0].u);//指定纹理指针

		 glDrawArrays(GL_QUADS,0,4);
	}
   
    virtual void    render(void)
    {
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	  static float tm = 0;

      tm += 1/60.0f *10;
	  if(tm >= 64)
	  {
		  tm = 0;
	  }
	  renderOrth(tm);
	}
};

int WINAPI WinMain( 
                      HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, 
                      int nCmdShow
                      )
{

    SamplerTexture    context;
    context.main(640,480);
    return  0;
}
  • 运行:













12月30日

  • 视频纹理(ffmpeg)
搭建ffmpeg环境:
①http://ffmpeg.org/ 官网下载,将下载完的bin、include、lib放在工程文件夹下
②配置属性
C/C++ --常规:../../include;./include
链接器--附加库目录:../../lib/$(PlatformName);./lib
链接器--输入:
OpenGL32.lib
glu32.lib
freeimage.lib
avcodec.lib
avdevice.lib
avfilter.lib
avformat.lib
avutil.lib
postproc.lib
swresample.lib
swscale.lib

1月19日

//FFMPEGVideoReader.h
#pragma once
//读取视频帧数据
extern "C"
{
#include <libavutil/imgutils.h>
#include <libavutil/parseutils.h>
#include <libswscale/swscale.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavutil/file.h>
}

class   FFMPEGVideoReader
{
public:
    AVFormatContext*pFormatCtx;
    int             i;
    int             videoindex;
    AVCodecContext* pCodecCtx;
    AVCodec*        pCodec;
    AVFrame*        pFrame;
    AVFrame*        pFrameRGB;
    SwsContext*     img_convert_ctx;
    int             screen_w;
    int             screen_h;
public:
    FFMPEGVideoReader()
    {
        av_register_all();//注册解码器
        avformat_network_init();//网络初始化
        pFormatCtx = avformat_alloc_context();//获得格式转化上下文
    }

    ~FFMPEGVideoReader() //析构 
    {
        sws_freeContext(img_convert_ctx);
        av_free(pFrameRGB);
        avcodec_close(pCodecCtx);
        avformat_close_input(&pFormatCtx);
    }

    int load(const char* filepath = "c:/FlickAnimation.avi")
    {
        FILE *fp_yuv;
        int     ret;
        int     got_picture;
        //打开
        if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0) 
        {
            return -1;
        }
		//查找
        if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
        {
            printf("Couldn't find stream information.\n");
            return -1;
        }
		//得到视频的索引
        videoindex = -1;
        for (i = 0; i < pFormatCtx->nb_streams; i++)
        {
            if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
            {
                videoindex = i;
                break;
            }
        }
        if (videoindex == -1) 
        {
            printf("Didn't find a video stream.\n");
            return -1;
        }
        pCodecCtx   =   pFormatCtx->streams[videoindex]->codec;
        pCodec      =   avcodec_find_decoder(pCodecCtx->codec_id);//找到解法器
        if (pCodec == NULL)
        {
            printf("Codec not found.\n");
            return -1;
        }
        if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) 
        {
            printf("Could not open codec.\n");
            return -1;
        }
        pFrame      =   av_frame_alloc();//原始的
        pFrameRGB   =   av_frame_alloc();//解码之后的
        //视频宽高
        screen_w    =   pCodecCtx->width;
        screen_h    =   pCodecCtx->height;

        img_convert_ctx = sws_getContext(
            pCodecCtx->width
            , pCodecCtx->height
            , pCodecCtx->pix_fmt
            , pCodecCtx->width
            , pCodecCtx->height
            , AV_PIX_FMT_RGB24
            , SWS_BICUBIC
            , NULL
            , NULL
            , NULL
            );

        if ((ret = av_image_alloc(dst_data, dst_linesize,
            pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, 1)) < 0)
        {
            fprintf(stderr, "Could not allocate destination image\n");
            return  -1;
        }
        return  0;
    }
    uint8_t *src_data[4], *dst_data[4];
    int src_linesize[4], dst_linesize[4];

    void*   readFrame()
    {
        AVPacket packet;
        av_init_packet(&packet);//初始化包
        for (;;) 
        {
            if (av_read_frame(pFormatCtx, &packet)) //包是否为完整包
            {
                av_free_packet(&packet);
                return 0;
            }


            if (packet.stream_index != videoindex) 
            {
                continue;
            }
            int frame_finished = 0;
            int res = avcodec_decode_video2(pCodecCtx, pFrame, &frame_finished, &packet);//解包

            if (frame_finished)
            {
                //转化
                int res = sws_scale(
                    img_convert_ctx
                    , (const uint8_t* const*)pFrame->data
                    , pFrame->linesize
                    , 0
                    , pCodecCtx->height
                    , dst_data
                    , dst_linesize
                    );//做转化
                av_free_packet(&packet);

                return  dst_data[0];
            }
        }

        return  0;
    }
};
//lesson418.cpp
#include <windows.h>
#include <tchar.h>
#include <math.h>

#include "FreeImage.h"

#include "CELLMath.hpp"

#include "OpenGLWindow.h"
#include <gl/GLU.h>
#include <vector>
#include "FFMPEGVideoReader.h"


using namespace CELL;

struct Vertex
{ 

    float x, y, z;
    float u, v;
};

class   SamplerTexture :public OpenGLWindow
{
    GLuint  _texture;

    float   _textureV;
    FFMPEGVideoReader _video;
public:
    SamplerTexture() 
    {
        _textureV   =   0;
    }

    virtual void    onShutdownGL()
    {
        glDeleteTextures(1,&_texture);
    }

    unsigned    createTexture(int w,int h, void* data)
    {
        unsigned    texId;
        glGenTextures(1,&texId);
        glBindTexture(GL_TEXTURE_2D,texId);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,w,h,0,GL_RGB,GL_UNSIGNED_BYTE,data);
        return  texId;
      
    }
    virtual void    onInitGL()
    {
        _video.load("C:\\Users\\dell\\Desktop\\源代码\\OpenGL-实战编码设计 - 副本\\source\\lesson418-视频纹理\\纹理矩阵控制.mp4");
        _texture    =   createTexture(_video.screen_w,_video.screen_h,0);
        
    }
    virtual void    render()
    {
#define M_PI (3.14159265358979323846)
        //! 指定以下的操作针对投影矩阵
        glMatrixMode(GL_PROJECTION);
        //! 将投影举证清空成单位矩阵
        glLoadIdentity();
        gluPerspective(80,double(_width)/double(_height),0.1,1000);
        Vertex cubeVertices[] =
        {
            {  -1.0f,-1, 1.0f    ,0,  1 },
            {  1.0f,-1, 1.0f     ,1,  1 },
            {  1.0f, 1, 1.0f     ,1,  0 },
            { -1.0f, 1, 1.0f     ,0,  0 },
        };

        glMatrixMode(GL_MODELVIEW);
        glBindTexture(GL_TEXTURE_2D,_texture);
		//下面两句每一帧来更新纹理
        void*   data    =   _video.readFrame();
        glTexSubImage2D(GL_TEXTURE_2D,0,0,0,_video.screen_w,_video.screen_h,GL_RGB,GL_UNSIGNED_BYTE,data);

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        glVertexPointer(3,GL_FLOAT,         sizeof(Vertex),     &cubeVertices[0].x);
        glTexCoordPointer(2,GL_FLOAT,       sizeof(Vertex),     &cubeVertices[0].u);

        //! 清成单位矩阵
        glLoadIdentity();
        //! 产生一个矩阵
        glTranslatef(0,0,-2);

        glDrawArrays( GL_QUADS, 0, 4 );

    }
};

int __stdcall WinMain( 
                      HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, 
                      int nShowCmd
                      )
{
    SamplerTexture    instance;
    instance.main(800,600);
    return  0;
}
  • 运行结果:













1月20日

  • 实现简单粒子系
 点精灵:openGL的图形由顶点构成,以后利用顶点进行纹理的映射。点精灵就是,一个顶点被当作一个精灵来处理。特别之处就是,一个顶点也可进行纹理贴出。例如,原来是个顶点构成的一个矩形,现在一个顶点就可以完成了。像粒子效果,云雾水流火花用了点精灵,就可以瞬间减少3个顶点的计算,glDrawArrays使用GL_POINT就可以了,完全也不需要什么顶点索引了。
 点精灵的局限:一个顶点缩放都必须是矩形。并且大小的最大最小值是有范围的,每个openGL的实现不一样需要查询获得。既然是一个纹理映射到一个顶点上,那么纹理映射就和原来完全不同,有些复杂。可能会抵消掉一些性能的优势。
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h"
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Particle
{ 
	float3 _curPos;//粒子位置
	float3 _curVel;//粒子速度
	unsigned char _r;
	unsigned char _g;
	unsigned char _b;
	unsigned char _a;
};

const int MAX_PARTICLES = 100;

class   Sprite :public OpenGLWindow
{
public:
	GLuint         _textureID;
	Particle       _particles[MAX_PARTICLES];//精灵数组
public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}

	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
	//得到的是方向
	float3 getRandomVector(void)
	{
		float3 vVector;
		vVector.z = rangeRandom(-1.0f,1.0f);
		float radius = (float)sqrt(1- vVector.z * vVector.z);//半径
		float t = rangeRandom(-PI,PI);
		vVector.x = (float)cosf(t) * radius;
		vVector.y = (float)sinf(t) * radius;
		return vVector;
	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);
		glEnable(GL_TEXTURE_2D);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_textureID   =   createTextureFromImage("particle.bmp");//构造纹理
		initPointSprites();
	}

	virtual void    onShutdownGL()
	{
		glDeleteTextures(1,&_textureID);
	}
	//初始化精灵
	void initPointSprites(void)
	{
		float maxSize = 0.0f;
		glGetFloatv(GL_POINT_SIZE_MAX_ARB,&maxSize);
		glPointSize(maxSize);
		//给所有精灵点数据初始化
		for(int i = 0; i< MAX_PARTICLES; ++i)
		{
			_particles[i]._curPos = float3(0.0f,0.0f,0.0f);
			_particles[i]._curVel = getRandomVector() * rangeRandom(0.5f,5.0f);//getRandomVector()随机产生飞行方向
			_particles[i]._r = rand()%255;
			_particles[i]._g = rand()%255;
			_particles[i]._b = rand()%255;
			_particles[i]._a = 255;
		}
	}
	//实时改变精灵位置
	void updatePointSprites(void)
	{
		static double dStartAppTime = timeGetTime();//得到当前时间,程序初始化就有
		//(timeGetTime()- dStartAppTime返回的是绘制一帧所需要的时间单位:毫秒;*0.001转化成秒
		float fElpasedAppTime = (float)((timeGetTime()- dStartAppTime)*0.001);

		static double dLastFrameTime = timeGetTime();
		double dCurrentFrameTime = timeGetTime();
		double dElpasedFrameTime = (float)((dCurrentFrameTime - dLastFrameTime) * 0.001);
		dLastFrameTime = dCurrentFrameTime;

		if(fElpasedAppTime >=5.0f)//时间到了,精灵到点
		{
			for(int i = 0;i< MAX_PARTICLES;++i)
				_particles[i]._curPos = float3(0.0f,0.0f,0.0f);
			dStartAppTime = timeGetTime();
		}
		for (int i =0;i<MAX_PARTICLES;++i)
			_particles[i]._curPos += _particles[i]._curVel * (float)dElpasedFrameTime;
	}
	//绘制
	void  renderPointSprites(void) 
	{
		//启动混合
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA,GL_ONE);
		float maxSize = 0.0f;
		glGetFloatv(GL_POINT_SIZE_MAX_ARB,&maxSize);
		if(maxSize>100.0f)
			maxSize = 100.0f;

        glPointSize(maxSize);

		glPointParameterfARB(GL_POINT_FADE_THRESHOLD_SIZE_ARB,60.0f);//指定点的阀值

		glPointParameterfARB(GL_POINT_SIZE_MIN_ARB,1.0f);
		glPointParameterfARB(GL_POINT_SIZE_MAX_ARB,maxSize);

		glTexEnvf(GL_POINT_SPRITE_ARB,GL_COORD_REPLACE_ARB,GL_TRUE);//纹理环境,用点精灵坐标替换当前坐标

		glEnable(GL_POINT_SPRITE_ARB);//启用顶点精灵

		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Particle),&_particles[0]._curPos.x);

		glEnableClientState(GL_COLOR_ARRAY);
		glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(Particle),&_particles[0]._r);

		glDrawArrays(GL_POINTS,0,MAX_PARTICLES);

		glDisable(GL_POINT_SPRITE_ARB);
	}
	virtual void render(void)
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-10.0f);

		updatePointSprites();

		glBindTexture(GL_TEXTURE_2D,_textureID);

		renderPointSprites();
	}
};


int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	Sprite    context;
	context.main(640,480);
	return  0;
}
  • 运行:













1月21日

  • 纹理应用-遮罩处理
 用到3个知识:正交投影(前面的圆环)透视投影(后面的三维) 纹理混合
  混合:混合就是把两种颜色混在一起。具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果。
假设我们需要绘制这样一个场景:透过红色的玻璃去看绿色的物体,那么可以先绘制绿色的物体,再绘制红色玻璃。在绘制红色玻璃的时候,利用“混合”功能,把将要绘制上去的红色和原来的绿色进行混合,于是得到一种新的颜色,看上去就好像玻璃是半透明的。
要使用OpenGL的混合功能,只需要调用:glEnable(GL_BLEND);即可。
要关闭OpenGL的混合功能,只需要调用:glDisable(GL_BLEND);即可。
注意:只有在RGBA模式下,才可以使用混合功能,颜色索引模式下是无法使用混合功能的。
  把将要画上去的颜色称为“源颜色”,把原来的颜色称为“目标颜色”。所谓源颜色和目标颜色,是跟绘制的顺序有关的。假如先绘制了一个红色的物体,再在其上绘制绿色的物体。则绿色是源颜色,红色是目标颜色。OpenGL会把源颜色和目标颜色各自取出,并乘以一个系数(源颜色乘以的系数称为“源因子”,目标颜色乘以的系数称为“目标因子”),然后相加,这样就得到了新的颜色。(也可以不是相加,新版本的OpenGL可以设置运算方式,包括加、减、取两者中较大的、取两者中较小的、逻辑运算等)。
  假设源颜色的四个分量(指红色,绿色,蓝色,alpha值)是(Rs, Gs, Bs,  As),目标颜色的四个分量是(Rd, Gd, Bd, Ad),又设源因子为(Sr, Sg, Sb, Sa),目标因子为(Dr, Dg, Db,  Da)。则混合产生的新颜色可以表示为:
(Rs*Sr+Rd*Dr, Gs*Sg+Gd*Dg, Bs*Sb+Bd*Db, As*Sa+Ad*Da)。如果颜色的某一分量超过了1.0,则它会被自动截取为1.0,不需要考虑越界的问题。
  源因子和目标因子是可以通过glBlendFunc函数来进行设置的。glBlendFunc有两个参数,前者表示源因子,后者表示目标因子。这两个参数可以是多种值,下面介绍比较常用的几种。
GL_ZERO:     表示使用0.0作为因子,实际上相当于不使用这种颜色参与混合运算。
GL_ONE:      表示使用1.0作为因子,实际上相当于完全的使用了这种颜色参与混合运算。
GL_SRC_ALPHA:表示使用源颜色的alpha值来作为因子。
GL_DST_ALPHA:表示使用目标颜色的alpha值来作为因子。
GL_ONE_MINUS_SRC_ALPHA:表示用1.0减去源颜色的alpha值来作为因子。
GL_ONE_MINUS_DST_ALPHA:表示用1.0减去目标颜色的alpha值来作为因子。
除此以外,还有GL_SRC_COLOR(把源颜色的四个分量分别作为因子的四个分量)、GL_ONE_MINUS_SRC_COLOR、 GL_DST_COLOR、GL_ONE_MINUS_DST_COLOR等,前两个在OpenGL旧版本中只能用于设置目标因子,后两个在OpenGL 旧版本中只能用于设置源因子。新版本的OpenGL则没有这个限制,并且支持新的GL_CONST_COLOR(设定一种常数颜色,将其四个分量分别作为 因子的四个分量)、GL_ONE_MINUS_CONST_COLOR、GL_CONST_ALPHA、 GL_ONE_MINUS_CONST_ALPHA。另外还有GL_SRC_ALPHA_SATURATE。新版本的OpenGL还允许颜色的alpha值和RGB值采用不同的混合因子。
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h"
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u,v;
};


class   Sprite :public OpenGLWindow
{
public:
	GLuint         _texture1;
	GLuint         _texture2;
	GLuint         _texture3;

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);
		glEnable(GL_TEXTURE_2D);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture1   =   createTextureFromImage("floor.bmp");
		_texture2   =   createTextureFromImage("CrossHair.bmp");
		_texture3   =   createTextureFromImage("CrossHairMask.bmp");
	}
	virtual void    onShutdownGL()
	{
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
		glDeleteTextures(1,&_texture3);
	}
	//绘制
	void  renderCube(void) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);
		//禁用顶点坐标
		glDisableClientState(GL_VERTEX_ARRAY);
		//禁用纹理坐标
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindTexture(GL_TEXTURE_2D,_texture1);

		glBegin(GL_QUADS);
		//指定纹理坐标   顶点坐标
		//BACK WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,-15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,-15);
		//FRONT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,15);
		//LEFT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(-15,1,15);
		//RIGHT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,15);

		glEnd();

		glBindTexture(GL_TEXTURE_2D,_texture1);

		glBegin(GL_QUADS);

		glTexCoord2f(0.0f,16.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(16.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(16.0f,16.0f);  glVertex3f(15,-1,-15);

		glEnd();

	}
	//画正交 遮罩
	void renderOrth()
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0,_width,_height,0,-100,100);//正交投影
		Vertex vert[] =
		{
			{0,           0,0,0.0f,1.0f},
			{0,     _height,0,0.0f,0.0f},
			{_width,_height,0,1.0f,0.0f},
			{_width,      0,0,1.0f,1.0f},
		};
		//可以不指定
		if(0)
			glColor4f(0,1,0,1);
		else
			glColor4f(1,1,1,1);

		glDisable(GL_DEPTH_TEST);//禁用深度,跟混合有关系
		//绘制第一次——————
		glBlendFunc(GL_DST_COLOR,GL_ZERO);//混合
		glEnable(GL_BLEND);
		glBindTexture(GL_TEXTURE_2D,_texture3);

		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&vert[0].x);

		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&vert[0].u);

		glDrawArrays(GL_QUADS,0,4);
		//———————————
		glBlendFunc(GL_ONE,GL_ONE);

		glBindTexture(GL_TEXTURE_2D,_texture2);
		glDrawArrays(GL_QUADS,0,4);

		glDisable(GL_BLEND);

		glEnable(GL_DEPTH_TEST);
	}
	virtual void render(void)
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//! 立方体
		renderCube();
		//! 遮罩
		renderOrth();
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	Sprite    context;
	context.main(640,480);
	return  0;
}
  • 运行:
遮罩处理
















1月22日

  • 纹理的管理

基于上节课代码,作相应的优化

  • 第一种方式(声明变量的方法)
 优点:看上去更直观
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h"
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include <map>
#include <string>

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u,v;
};

class TextureManager:public std::map<std::string,GLuint>
{
public:
	GLuint getTexture(const char* fileName)
	{
		iterator itr = find(fileName);//查找是否在map当中
		if(itr != end())
		{
            return itr->second;//返回纹理的id
		}
		else
		{
			GLuint res = createTextureFromImage(fileName);
		    if(res != 0)
			{
                (*this)[fileName]  =  res;//放到map中去
			}
			return res;
		}
	}

	void   releaseTexture(GLuint texId)
	{

	}
protected:
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
};

class   Sprite :public OpenGLWindow
{
public:
	GLuint         _texture1;
	GLuint         _texture2;
	GLuint         _texture3;
	TextureManager _texMgr;

public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);
		glEnable(GL_TEXTURE_2D);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture1   =   _texMgr.getTexture("floor.bmp");
		_texture2   =   _texMgr.getTexture("CrossHair.bmp");
		_texture3   =   _texMgr.getTexture("CrossHairMask.bmp");
	}
	virtual void    onShutdownGL()
	{
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
		glDeleteTextures(1,&_texture3);
	}
	//绘制
	void  renderCube(void) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);
		//禁用顶点坐标
		glDisableClientState(GL_VERTEX_ARRAY);
		//禁用纹理坐标
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindTexture(GL_TEXTURE_2D,_texture1);

		glBegin(GL_QUADS);
		//指定纹理坐标   顶点坐标
		//BACK WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,-15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,-15);
		//FRONT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,15);
		//LEFT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(-15,1,15);
		//RIGHT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,15);

		glEnd();

		glBindTexture(GL_TEXTURE_2D,_texture1);

		glBegin(GL_QUADS);

		glTexCoord2f(0.0f,16.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(16.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(16.0f,16.0f);  glVertex3f(15,-1,-15);

		glEnd();

	}
	//画正交 遮罩
	void renderOrth()
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0,_width,_height,0,-100,100);//正交投影
		Vertex vert[] =
		{
			{0,           0,0,0.0f,1.0f},
			{0,     _height,0,0.0f,0.0f},
			{_width,_height,0,1.0f,0.0f},
			{_width,      0,0,1.0f,1.0f},
		};
		//可以不指定
		if(0)
			glColor4f(0,1,0,1);
		else
			glColor4f(1,1,1,1);

		glDisable(GL_DEPTH_TEST);//禁用深度,跟混合有关系
		//绘制第一次——————
		glBlendFunc(GL_DST_COLOR,GL_ZERO);//混合
		glEnable(GL_BLEND);
		glBindTexture(GL_TEXTURE_2D,_texture3);

		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&vert[0].x);

		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&vert[0].u);

		glDrawArrays(GL_QUADS,0,4);
		//———————————
		glBlendFunc(GL_ONE,GL_ONE);

		glBindTexture(GL_TEXTURE_2D,_texture2);
		glDrawArrays(GL_QUADS,0,4);

		glDisable(GL_BLEND);

		glEnable(GL_DEPTH_TEST);
	}
	virtual void render(void)
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//! 立方体
		renderCube();
		//! 遮罩
		renderOrth();
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	Sprite    context;
	context.main(640,480);
	return  0;
}
  • 运行结果不变
  • 第二种方法:派生类(从面向对象编程的角度来说,更建议这种方式)
 优点:可以少写一个成员变量;缺点:OpenGLWindow和派生类TextureManager 里函数冲突(所以最好加上作用域访问)
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h"
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include <map>
#include <string>

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u,v;
};

class TextureManager:public std::map<std::string,GLuint>
{
public:
	GLuint getTexture(const char* fileName)
	{
		iterator itr = find(fileName);//查找是否在map当中
		if(itr != end())
		{
            return itr->second;//返回纹理的id
		}
		else
		{
			GLuint res = createTextureFromImage(fileName);
		    if(res != 0)
			{
                (*this)[fileName]  =  res;//放到map中去
			}
			return res;
		}
	}
protected:
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
};

class   Sprite 
	:public OpenGLWindow
	,public TextureManager //派生 类
{
public:
	GLuint         _texture1;
	GLuint         _texture2;
	GLuint         _texture3;

public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);
		glEnable(GL_TEXTURE_2D);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture1   =   TextureManager::getTexture("floor.bmp");
		_texture2   =   TextureManager::getTexture("CrossHair.bmp");
		_texture3   =   getTexture("CrossHairMask.bmp");
	}
	virtual void    onShutdownGL()
	{
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
		glDeleteTextures(1,&_texture3);
	}
	//绘制
	void  renderCube(void) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);
		//禁用顶点坐标
		glDisableClientState(GL_VERTEX_ARRAY);
		//禁用纹理坐标
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindTexture(GL_TEXTURE_2D,_texture1);

		glBegin(GL_QUADS);
		//指定纹理坐标   顶点坐标
		//BACK WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,-15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,-15);
		//FRONT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,15);
		//LEFT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(-15,1,15);
		//RIGHT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,15);

		glEnd();

		glBindTexture(GL_TEXTURE_2D,_texture1);

		glBegin(GL_QUADS);

		glTexCoord2f(0.0f,16.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(16.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(16.0f,16.0f);  glVertex3f(15,-1,-15);

		glEnd();

	}
	//画正交 遮罩
	void renderOrth()
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0,_width,_height,0,-100,100);//正交投影
		Vertex vert[] =
		{
			{0,           0,0,0.0f,1.0f},
			{0,     _height,0,0.0f,0.0f},
			{_width,_height,0,1.0f,0.0f},
			{_width,      0,0,1.0f,1.0f},
		};
		//可以不指定
		if(0)
			glColor4f(0,1,0,1);
		else
			glColor4f(1,1,1,1);

		glDisable(GL_DEPTH_TEST);//禁用深度,跟混合有关系
		//绘制第一次——————
		glBlendFunc(GL_DST_COLOR,GL_ZERO);//混合
		glEnable(GL_BLEND);
		glBindTexture(GL_TEXTURE_2D,_texture3);

		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&vert[0].x);

		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&vert[0].u);

		glDrawArrays(GL_QUADS,0,4);
		//———————————
		glBlendFunc(GL_ONE,GL_ONE);

		glBindTexture(GL_TEXTURE_2D,_texture2);
		glDrawArrays(GL_QUADS,0,4);

		glDisable(GL_BLEND);

		glEnable(GL_DEPTH_TEST);
	}
	virtual void render(void)
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//! 立方体
		renderCube();
		//! 遮罩
		renderOrth();
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	Sprite    context;
	context.main(640,480);
	return  0;
}
  • 组管理资源
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h"
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include <map>
#include <string>

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u,v;
};

typedef std::map<std::string,GLuint>       MapTexture;
typedef std::map<std::string,MapTexture>   MapGroup;

class TextureManager:public MapGroup
{
public:
	GLuint getTexture(const char* fileName,const char* group ="defaut")//组下面有一系列资源管理
	{
		MapTexture& grp   =   (*this)[group];
		MapTexture::iterator  itr = grp.find(fileName);//查找是否在map当中
		if(itr != grp.end())
		{
            return itr->second;//返回纹理的id
		}
		else
		{
			GLuint res = createTextureFromImage(fileName);
		    if(res != 0)
			{
                (*this)[group][fileName]  =  res;//放到map中去
			}
			return res;
		}
	}
void releaseGroup(const char* group= "defaut")
{
	MapTexture& grp = (*this)[group];
	MapTexture::iterator itrR  =  grp.begin();//注意此迭代器不要与上面重复
	for( ;itrR != grp.end();++itrR)
	{
			glDeleteTextures(1,&itrR->second);
	}
	grp.clear();
}
 void releaseTexture(GLuint tex,const char* group = 0) //组给空,则遍历所有的组,给定组则在给定组下释放资源
 {
	 if(group == 0)
	 {
		 for (iterator itr = begin();itr != end();++itr)
		 {
            MapTexture& grp = itr->second;
			MapTexture::iterator itrR  =  grp.begin();//注意此迭代器不要与上面重复
		    for( ;itrR != grp.end();++itr)
			{
               if (itrR->second == tex)
               {
				   glDeleteTextures(1,&itrR->second);
                  grp.erase(itrR);
				  return;
               }
			}
		 }
	 }
	 else
	 {
		 MapTexture& grp = (*this)[group];
		 MapTexture::iterator itrR  =  grp.begin();//注意此迭代器不要与上面重复
		 for( ;itrR != grp.end();++itrR)
			{
				if (itrR->second == tex)
				{
					glDeleteTextures(1,&itrR->second);
					grp.erase(itrR);
					break;
				}
			}
	 }
 }

protected:
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
};

class   Sprite 
	:public OpenGLWindow
	,public TextureManager //派生 类
{
public:
	GLuint         _texture1;
	GLuint         _texture2;
	GLuint         _texture3;

public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);
		glEnable(GL_TEXTURE_2D);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture1   =   TextureManager::getTexture("floor.bmp");
		_texture2   =   TextureManager::getTexture("CrossHair.bmp");
		_texture3   =   getTexture("CrossHairMask.bmp");
	}
	virtual void    onShutdownGL()
	{
		releaseGroup();
	}
	//绘制
	void  renderCube(void) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);
		//禁用顶点坐标
		glDisableClientState(GL_VERTEX_ARRAY);
		//禁用纹理坐标
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindTexture(GL_TEXTURE_2D,_texture1);

		glBegin(GL_QUADS);
		//指定纹理坐标   顶点坐标
		//BACK WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,-15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,-15);
		//FRONT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,15);
		//LEFT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(-15,1,15);
		//RIGHT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,15);

		glEnd();

		glBindTexture(GL_TEXTURE_2D,_texture1);

		glBegin(GL_QUADS);

		glTexCoord2f(0.0f,16.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(16.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(16.0f,16.0f);  glVertex3f(15,-1,-15);

		glEnd();

	}
	//画正交 遮罩
	void renderOrth()
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0,_width,_height,0,-100,100);//正交投影
		Vertex vert[] =
		{
			{0,           0,0,0.0f,1.0f},
			{0,     _height,0,0.0f,0.0f},
			{_width,_height,0,1.0f,0.0f},
			{_width,      0,0,1.0f,1.0f},
		};
		//可以不指定
		if(0)
			glColor4f(0,1,0,1);
		else
			glColor4f(1,1,1,1);

		glDisable(GL_DEPTH_TEST);//禁用深度,跟混合有关系
		//绘制第一次——————
		glBlendFunc(GL_DST_COLOR,GL_ZERO);//混合
		glEnable(GL_BLEND);
		glBindTexture(GL_TEXTURE_2D,_texture3);

		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&vert[0].x);

		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&vert[0].u);

		glDrawArrays(GL_QUADS,0,4);
		//———————————
		glBlendFunc(GL_ONE,GL_ONE);

		glBindTexture(GL_TEXTURE_2D,_texture2);
		glDrawArrays(GL_QUADS,0,4);

		glDisable(GL_BLEND);

		glEnable(GL_DEPTH_TEST);
	}
	virtual void render(void)
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//! 立方体
		renderCube();
		//! 遮罩
		renderOrth();
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	Sprite    context;
	context.main(640,480);
	return  0;
}

1月23日

  • 第5章 显存-控制-性能提升
  • displaylist(显示列表)
在OpenGL中,显示列表是由一组预先存储起来的留待以后调用的OpenGL函数语句组成,当调用这张显示列表时就依次执行表中所列出的函数语句。显示列表的设计目的在于优化OpenGL程序的运行性能。【把动作做成显示列表,不放在客户端,而是放在OpenGL的服务端(显卡端),提高了效率】
优点:速度快;缺点:对内存和显存有一定的要求
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h"
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u,v;
};


class   Sprite :public OpenGLWindow
{
public:
	GLuint         _texture1;
	GLuint         _texture2;
	GLuint         _texture3;
	GLuint         _cubeDisplay;
	GLuint         _maskDisplay;

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);
		glEnable(GL_TEXTURE_2D);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture1   =   createTextureFromImage("floor.bmp");
		_texture2   =   createTextureFromImage("CrossHair.bmp");
		_texture3   =   createTextureFromImage("CrossHairMask.bmp");
	
		_cubeDisplay  =  1;
		glNewList(_cubeDisplay,GL_COMPILE);//创建显示列表;GL_COMPILE:编译 GL_COMPILE_AND_EXECUTE:编译且执行
		     renderCube();
	    glEndList();

		_maskDisplay  =  2;
		glNewList(_maskDisplay,GL_COMPILE);
		     renderOrth();
		glEndList();
	
	}
	virtual void    onShutdownGL()
	{
		glDeleteTextures(1,&_texture1);
		glDeleteTextures(1,&_texture2);
		glDeleteTextures(1,&_texture3);

		glDeleteLists(_cubeDisplay,1);
        glDeleteLists(_maskDisplay,1);
	}
	//绘制
	void  renderCube(void) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);
		//禁用顶点坐标
		glDisableClientState(GL_VERTEX_ARRAY);
		//禁用纹理坐标
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindTexture(GL_TEXTURE_2D,_texture1);

		glBegin(GL_QUADS);
		//指定纹理坐标   顶点坐标
		//BACK WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,-15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,-15);
		//FRONT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,15);
		//LEFT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(-15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(-15,1,15);
		//RIGHT WALL
		glTexCoord2f(0.0f,2.0f);  glVertex3f(15,1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(15,-1,-15);
		glTexCoord2f(12.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(12.0f,2.0f);  glVertex3f(15,1,15);

		glEnd();

		glBindTexture(GL_TEXTURE_2D,_texture1);

		glBegin(GL_QUADS);

		glTexCoord2f(0.0f,16.0f);  glVertex3f(-15,-1,-15);
		glTexCoord2f(0.0f,0.0f);  glVertex3f(-15,-1,15);
		glTexCoord2f(16.0f,0.0f);  glVertex3f(15,-1,15);
		glTexCoord2f(16.0f,16.0f);  glVertex3f(15,-1,-15);

		glEnd();

	}
	//画正交 遮罩
	void renderOrth()
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		glOrtho(0,_width,_height,0,-100,100);//正交投影
		Vertex vert[] =
		{
			{0,           0,0,0.0f,1.0f},
			{0,     _height,0,0.0f,0.0f},
			{_width,_height,0,1.0f,0.0f},
			{_width,      0,0,1.0f,1.0f},
		};
		//可以不指定
		if(0)
			glColor4f(0,1,0,1);
		else
			glColor4f(1,1,1,1);

		glDisable(GL_DEPTH_TEST);//禁用深度,跟混合有关系
		//绘制第一次——————
		glBlendFunc(GL_DST_COLOR,GL_ZERO);//混合
		glEnable(GL_BLEND);
		glBindTexture(GL_TEXTURE_2D,_texture3);

		glEnableClientState(GL_VERTEX_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&vert[0].x);

		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&vert[0].u);

		glDrawArrays(GL_QUADS,0,4);
		//———————————
		glBlendFunc(GL_ONE,GL_ONE);

		glBindTexture(GL_TEXTURE_2D,_texture2);
		glDrawArrays(GL_QUADS,0,4);

		glDisable(GL_BLEND);

		glEnable(GL_DEPTH_TEST);
	}
	virtual void render(void)
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//! 立方体
		//renderCube();

		unsigned char list[] = {_cubeDisplay,_maskDisplay};
		glListBase(0);//指定显示列表从多少开始
		
		glCallLists(2,GL_UNSIGNED_BYTE,list);
		//glCallList(_cubeDisplay);
		//! 遮罩
		//renderOrth();
        //glCallList(_maskDisplay);
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	Sprite    context;
	context.main(640,480);
	return  0;
}
  • 运行结果不变
  • VBO 顶点缓冲区(做顶点优化的一种手段)
绘制时候用的最多的就是顶点数据,VertexBufferObject就是OpenGL提供一个通道,通过调用函数,直接分配显存专门用来存放顶点数据

1月24日

//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h"
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u,v;
	float   r,g,b;
};
//提前把数据放显卡,绘制时候直接从显卡里取数据绘,减少了数据从内存到显存的传输过程,提高了效率
Vertex g_cubeVertices[] =
{
	{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
	{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
	{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
	{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

	{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
	{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
	{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
	{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

	{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
	{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
	{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
	{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

	{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
	{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
	{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
	{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

	{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
	{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
	{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
	{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

	{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
	{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
	{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
	{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
};

class   VertexBufferObject :public OpenGLWindow
{
public:
	GLuint         _texture;
	GLuint         _vbo;

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);
		glEnable(GL_TEXTURE_2D);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		

		glGenBuffers(1,&_vbo);//只产生一个对象id,并不实际分配显存
	    glBindBuffer(GL_ARRAY_BUFFER,_vbo);//绑定
        //传送数据到显卡中,同时也分配了一块显存,将数据拷贝进去
        glBufferData(GL_ARRAY_BUFFER,sizeof(g_cubeVertices),g_cubeVertices,GL_STATIC_DRAW);//GL_STATIC_DRAW静态绘制

		glBindBuffer(GL_ARRAY_BUFFER,0);//恢复状态
	
	}
	virtual void    onShutdownGL()
	{
		glDeleteBuffers(1,&_vbo);

	}
	//绘制
	void  renderCube(void) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		glBindTexture(GL_TEXTURE_2D,_texture);

		glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindBuffer(GL_ARRAY_BUFFER,_vbo);//告诉下面函数去显存取数据  _vbo为显存首地址
		
		float* addrVertex = (float*)g_cubeVertices;
        float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


        //顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),0 );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),(void*)20);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),(void*)12);

		glDrawArrays(GL_QUADS,0,24);
	}
	
	virtual void render(void)
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//! 立方体
		renderCube();
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	VertexBufferObject    context;
	context.main(640,480);
	return  0;
}
  • 运行结果:
VBO
















  • IBO 索引缓冲区 节约很多内存
//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   r,g,b;
	float   x,y,z;
};
//提前把数据放显卡,绘制时候直接从显卡里取数据绘,减少了数据从内存到显存的传输过程,提高了效率
Vertex g_cubeVertices[] =
{
	{ 1.0f,0.0f, 0.0f,-1.0f, -1.0f, 1.0f }, //0
	{ 0.0f,1.0f, 0.0f, 1.0f, -1.0f, 1.0f }, //1
	{ 0.0f,0.0f, 1.0f, 1.0f,  1.0f, 1.0f }, //2
	{ 1.0f,1.0f, 0.0f,-1.0f,  1.0f, 1.0f }, //3
	{ 1.0f,0.0f, 1.0f,-1.0f, -1.0f,-1.0f }, //4
	{ 0.0f,1.0f, 1.0f,-1.0f,  1.0f,-1.0f }, //5
	{ 1.0f,1.0f, 1.0f, 1.0f,  1.0f,-1.0f }, //6
	{ 1.0f,0.0f, 0.0f, 1.0f, -1.0f,-1.0f }, //7
};

//共占字节数:6 * 4 +4 * 4 * 6 = 120;
//原来占字节:24 * 24 = 576;

GLubyte g_cubeIndices[] = //索引方式
{
	0,1,2,3, // Quad 0 占4个字节
	4,5,6,7, // Quad 1
	5,3,2,6, // Quad 2
	4,7,1,0, // Quad 3
	7,6,2,1, // Quad 4
	4,0,3,5  // Quad 5
};
class   IndexBufferObject :public OpenGLWindow
{
public:
	GLuint         _texture;
	GLuint         _vbo;
	GLuint         _ibo;

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		

		glGenBuffers(1,&_vbo);//只产生一个对象id,并不实际分配显存
	    glBindBuffer(GL_ARRAY_BUFFER,_vbo);//绑定
        //传送数据到显卡中,同时也分配了一块显存,将数据拷贝进去
        glBufferData(GL_ARRAY_BUFFER,sizeof(g_cubeVertices),g_cubeVertices,GL_STATIC_DRAW);//GL_STATIC_DRAW静态绘制

		glBindBuffer(GL_ARRAY_BUFFER,0);//恢复状态

		glGenBuffers(1,&_ibo);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_ibo);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(g_cubeIndices),g_cubeIndices,GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
	
	}
	virtual void    onShutdownGL()
	{
		glDeleteBuffers(1,&_vbo);

	}
	//绘制
	void  renderCube(void) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		glBindBuffer(GL_ARRAY_BUFFER,_vbo);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_ibo);
		
		glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		glBindBuffer(GL_ARRAY_BUFFER,_vbo);//告诉下面函数去显存取数据  _vbo为显存首地址
		
		glEnableClientState(GL_VERTEX_ARRAY);

		glEnableClientState(GL_COLOR_ARRAY);

		float* addrVertex = (float*)12;
		float* colorAddress = (float*)0;


        //顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		
		glDrawElements(GL_QUADS,24,GL_UNSIGNED_BYTE,0);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);

	}
	
	virtual void render(void)
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//! 立方体
		renderCube();
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	IndexBufferObject    context;
	context.main(640,480);
	return  0;
}
  • 运行:
IBO
















1月25日

  • PBuffer-实现离屏渲染
  离屏渲染就是渲染的结果保存在系统内存中,屏幕上并不显示,而屏幕渲染是渲染的结果直接在屏幕上显示出来。
  OpenGL的窗口没有正常显示,则读取窗口数据是读不到的。
  如果要截屏,窗口屏幕一定是看得到的情况下才能截到。(数据在后台运行是截不到的),如果要实现数据在后台运算,并把数据保留下来,就要用到PBuffer。
  建立PBuffer,实际上建立一个OpenGL对象,这个OpenGL对象是在后台绘制,并不把数据绘制在窗口上
//PixelBuffer.h
#pragma once

#include "glew/glew.h"
#include "glew/wglew.h"
class   PixelBuffer
{
public:
    HPBUFFERARB _hPBuffer;
    HDC         _hDC;
    HWND        _hWnd;
    HGLRC       _hRC;//上下文
    int         _width;
    int         _height;
public:
    /**
    *   建立
    */
    bool    setup(HWND hWnd, HDC hDC, HGLRC hRC,int w, int h)//hRC主窗口对象
    {
        _hWnd   =   hWnd;
        _width  =   w;
        _height =   h;

        int pf_attr[] = //PBuffer属性
        {
            WGL_SUPPORT_OPENGL_ARB, TRUE,       // P-buffer will be used with OpenGL
            WGL_DRAW_TO_PBUFFER_ARB, TRUE,      // Enable render to p-buffer
            WGL_RED_BITS_ARB, 8,                // At least 8 bits for RED channel
            WGL_GREEN_BITS_ARB, 8,              // At least 8 bits for GREEN channel
            WGL_BLUE_BITS_ARB, 8,               // At least 8 bits for BLUE channel
            WGL_ALPHA_BITS_ARB, 8,              // At least 8 bits for ALPHA channel
            WGL_DEPTH_BITS_ARB, 16,             // At least 16 bits for depth buffer
            WGL_DOUBLE_BUFFER_ARB, FALSE,       // We don't require double buffering
            0                                   // Zero terminates the list
        };

        unsigned    count = 0;
        int         pixelFormat;
        wglChoosePixelFormatARB(hDC, (const int*)pf_attr, NULL, 1, &pixelFormat, &count);//选择跟属性相匹配的pixelFormat

        if (count == 0)
        {
            return  false;
        }

        _hPBuffer   =   wglCreatePbufferARB(hDC, pixelFormat, _width, _height, NULL);//创建一个PBuffer,用于存取数据的缓冲区
        _hDC        =   wglGetPbufferDCARB(_hPBuffer);
        _hRC        =   wglCreateContext(_hDC);

        if (_hPBuffer == 0)
        {
            return  false;
        }
        //查询PBuffer的宽高
        wglQueryPbufferARB(_hPBuffer, WGL_PBUFFER_WIDTH_ARB, &w);
        wglQueryPbufferARB(_hPBuffer, WGL_PBUFFER_HEIGHT_ARB, &h);

        if (h != _height || w != _width)
        {
            return  false;
        }


        if (!wglMakeCurrent(_hDC, _hRC))//将_hDC和_hRC关联起来
        {
            return  false;
        }


        if (!wglShareLists(hRC, _hRC))//_hRC从对象可以使用hRC主对象里的资源
        {
            return  false;
        }

        return  true;
    }

    void    makeCurrent()
    {
        wglMakeCurrent(_hDC, _hRC);
    }

    void    end()
    {

    }

    /**
    *   销毁
    */
    void    destroy()
    {
        if (_hRC != NULL)
        {
            wglMakeCurrent(_hDC, _hRC);
            wglDeleteContext(_hRC);
            wglReleasePbufferDCARB(_hPBuffer, _hDC);
            wglDestroyPbufferARB(_hPBuffer);
            _hRC = NULL;
        }
        if (_hDC)
        {
            ReleaseDC(_hWnd, _hDC);
            _hDC = 0;
        }
    }
};
//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "PixelBuffer.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
    float   u, v;
	float   r,g,b;
};

class   PBOWindow :public OpenGLWindow
{
public:
	GLuint         _texture;
	PixelBuffer    _pbuffer;

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————
		_pbuffer.setup(_hWnd,_hDC,_hRC,453,605);
		glEnable(GL_TEXTURE_2D);
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};

		
		glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;
        

        //顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}
	
	virtual void render(void)
	{
        _pbuffer.makeCurrent();

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//! 立方体
		renderCube(_texture);
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	PBOWindow    context;
	context.main(640,480);
	return  0;
}
  • 验证:
验证思路:
将PBuffer里的内容存到_dynamic中,再绘制就用_dynamic内容贴到立方体上去进行验证
//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "PixelBuffer.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
    float   u, v;
	float   r,g,b;
};

class   PBOWindow :public OpenGLWindow
{
public:
	GLuint         _texture;
	PixelBuffer    _pbuffer;
    GLuint         _dynamic;

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————
		_pbuffer.setup(_hWnd,_hDC,_hRC,640,480);
		glEnable(GL_TEXTURE_2D);
		_dynamic   =   createTexture(_pbuffer._width,_pbuffer._height,0,GL_RGBA);
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle = 0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			++angle;
		}
		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};

		
		glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;
        

        //顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}
	
	virtual void render(void)
	{
        _pbuffer.makeCurrent();
        
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_DEPTH_TEST);       
		renderCube(_texture,true);
		glBindTexture(GL_TEXTURE_2D,_dynamic);
		glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,_pbuffer._width,_pbuffer._height);//将PBuffer内容拷到纹理中来

		makeCurrent();
		glDisable(GL_DEPTH_TEST);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//! 立方体
		renderCube(_dynamic,false);
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	PBOWindow    context;
	context.main(640,480);
	return  0;
}
  • 运行:













1月26日

  • FBO(另一种离屏渲染的方式)
  在OpenGL中所有的图形,都会绘制到 FrameBufferObject 上。如果想使用界面的做分屏渲染,或需要屏幕图像制成贴图以备后期处理,就需要用到 FrameBufferObject 技术,这种方式也被称为 RTT (Render to Texture)。
  思路:  
  通过:glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,colorBuffer,0);     可以将ColorBuffer绑定到一张Texture上。当然也可以绑定到多张贴图中。另外使用这个函数也可以取出深度贴图。
  然后在实际渲染时使用fbo中的贴图进行绘制。
当生成了自己的fbo之后,即可将图元绘制到贴图上面,可以理解为是一个预渲染的过程。
//FrameBufferObject.h
#pragma once

#include "glew/glew.h"

class   FrameBufferObject//帧缓存对象
{
public:
    unsigned    _width;
    unsigned    _height;
    unsigned    _FBOID;
    unsigned    _RBOID;
public:
    /**
    *   建立
    */
    bool    setup(int w, int h)
    {
        _width  =   w;
        _height =   h;
        glGenFramebuffers(1, &_FBOID);//产生对象,并不实际分配空间
        glBindFramebuffer(GL_FRAMEBUFFER, _FBOID);//绑定

        glGenRenderbuffers(1, &_RBOID);
        glBindRenderbuffer(GL_RENDERBUFFER, _RBOID);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _width, _height);//存储16位深度内容

        glBindRenderbuffer(GL_RENDERBUFFER, 0);
        //将Framebuffer和Renderbuffer做关联,关联1个深度缓冲区,16个颜色缓冲区
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _RBOID);
        //颜色缓冲区用纹理代替
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        return  true;
    }

    void    begin(GLuint textureId) //传进去纹理
    {
        glBindFramebuffer(GL_FRAMEBUFFER, _FBOID);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);//颜色深度存入textureId
        glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _RBOID );

    }

    void    end()
    {
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
    }

    /**
    *   销毁
    */
    void    destroy()
    {
        glDeleteFramebuffers(1, &_FBOID);
        glDeleteRenderbuffers(1,&_RBOID);
        _RBOID  =   0;
        _FBOID  =   0;
    }
};
//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
    float   u, v;
	float   r,g,b;
};

class   PBOWindow :public OpenGLWindow
{
public:
	GLuint              _texture;
	FrameBufferObject   _fbo;
    GLuint              _textureId;//用于存储FrameBuffer绘制的结果

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————
	    
		_fbo.setup(640,480);
		_textureId = createTexture(_fbo._width,_height,0,GL_RGBA);
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};

		
		glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;
        

        //顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}
	
	virtual void render(void)
	{
        _fbo.begin(_textureId);

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		renderCube(_texture);
        _fbo.end();
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	PBOWindow    context;
	context.main(640,480);
	return  0;
}

1月27日

  • FBO验证:
//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   FBOWindow :public OpenGLWindow
{
public:
	GLuint              _texture;
	FrameBufferObject   _fbo;
	GLuint              _textureId;//用于存储FrameBuffer绘制的结果

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————

		_fbo.setup(640,480);
		_textureId = createTexture(_fbo._width,_height,0,GL_RGBA);
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle  =  0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			angle += 1;
		}

		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	virtual void render(void)
	{
		_fbo.begin(_textureId);

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		renderCube(_texture,true);
		_fbo.end ();

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		renderCube(_textureId,false);
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	FBOWindow    context;
	context.main(640,480);
	return  0;
}
  • 运行:












总结:
1、glEnable(GL_DEPTH_TEST);深度测试影响整个绘制,因为只有一个OpenGL的上下文
2、_textureId创建的大小一定要和_fbo大小一样,否则就会失败
3、_fbo不需要创建额外的上下文
4、_fbo更加灵活,占用的内存更少

1月28日

  • 读取屏幕内容(从屏幕/FBO/PBP(显卡中)读出数据放入内存)
  • 从屏幕读数据:
//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   FBOWindow :public OpenGLWindow
{
public:
	GLuint              _texture;
	FrameBufferObject   _fbo;
	GLuint              _textureId;//用于存储FrameBuffer绘制的结果

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————

		_fbo.setup(640,480);
		_textureId = createTexture(_fbo._width,_height,0,GL_RGBA);
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle  =  0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			angle += 1;
		}

		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	virtual void render(void)
	{
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		renderCube(_texture,false);

		RECT rect;//当前窗口
		GetClientRect(_hWnd,&rect);
		int  w = rect.right  -  rect.left;
		int  h = rect.bottom  -  rect.top;
		unsigned char* data= new unsigned char[w * h *4];//4通道
        memset(data,0,w * h * 4);
		glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,data);//读出当前屏幕内容,只能是GL_RGBA
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	FBOWindow    context;
	context.main(640,480);
	return  0;
}

1月29日

  • 验证:
读取屏幕内容(原来为空)









运行后:

读屏幕内容-捕获到数据








  • 从FBO读数据:
//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   FBOWindow :public OpenGLWindow
{
public:
	GLuint              _texture;
	FrameBufferObject   _fbo;
	GLuint              _textureId;//用于存储FrameBuffer绘制的结果

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————

		_fbo.setup(640,480);
		_textureId = createTexture(_fbo._width,_height,0,GL_RGBA);
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle  =  0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			angle += 1;
		}

		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	virtual void render(void)
	{

        _fbo.begin(_textureId);

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        renderCube(_texture,true);
 
		RECT rect;//当前窗口
		GetClientRect(_hWnd,&rect);
		int  w = rect.right  -  rect.left;
		int  h = rect.bottom  -  rect.top;
		unsigned char* data = new unsigned char[w * h *4];//4通道
		memset(data,0,w * h * 4);
		glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,data);//读出当前屏幕内容,只能是GL_RGBA
		
		_fbo.end();
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	FBOWindow    context;
	context.main(640,480);
	return  0;
}
  • 从PBuffer读数据:
//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "PixelBuffer.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   PBOWindow :public OpenGLWindow
{
public:
	GLuint         _texture;
	PixelBuffer    _pbuffer;
	GLuint         _dynamic;

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————
		_pbuffer.setup(_hWnd,_hDC,_hRC,640,480);
		glEnable(GL_TEXTURE_2D);
		_dynamic   =   createTexture(_pbuffer._width,_pbuffer._height,0,GL_RGBA);
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle = 0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			++angle;
		}
		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	virtual void render(void)
	{
		_pbuffer.makeCurrent();

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glEnable(GL_DEPTH_TEST);       
		renderCube(_texture,true);
		glBindTexture(GL_TEXTURE_2D,_dynamic);
		glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,_pbuffer._width,_pbuffer._height);//将PBuffer内容拷到纹理中来

		RECT rect;//当前窗口
		GetClientRect(_hWnd,&rect);
		int  w = rect.right  -  rect.left;
		int  h = rect.bottom  -  rect.top;
		unsigned char* data = new unsigned char[w * h *4];//4通道
		memset(data,0,w * h * 4);
		glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,data);//读出当前屏幕内容,只能是GL_RGBA
        

		makeCurrent();
		glDisable(GL_DEPTH_TEST);
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//! 立方体
		renderCube(_dynamic,false);
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	PBOWindow    context;
	context.main(640,480);
	return  0;
}

1月30日

  • 读取屏幕数据保存文件
	  //创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

	  using namespace CELL;

#pragma comment(lib,"winmm.lib")

  struct Vertex
  { 
	  float   x,y,z;
	  float   u, v;
	  float   r,g,b;
  };

  class   FBOWindow :public OpenGLWindow
  {
  public:
	  GLuint              _texture;
	  FrameBufferObject   _fbo;
	  GLuint              _textureId;//用于存储FrameBuffer绘制的结果

  public:
	  /*使用FreeImage加载图片*/
	  unsigned createTexture(int w,int h,const void* data,GLenum type)
	  {
		  unsigned texId;
		  glGenTextures(1,&texId);//产生纹理
		  glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		  glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		  return texId;
	  }
	  unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	  {
		  //获取图片格式
		  FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		  if(fifmt == FIF_UNKNOWN)
		  {
			  return 0;
		  }
		  //加载图片
		  FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		  FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		  //获取数据指针
		  FIBITMAP* temp  =  dib;
		  dib = FreeImage_ConvertTo32Bits(dib);
		  FreeImage_Unload(temp);//释放原来对象

		  BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		  int width = FreeImage_GetWidth(dib);
		  int height = FreeImage_GetHeight(dib);

		  for (int i = 0; i < width * height * 4; i += 4)
		  {
			  BYTE temp = pixels[i];
			  pixels[i] = pixels[i + 2];
			  pixels[i + 2] = temp;
		  }

		  unsigned res = createTexture(width,height,pixels,GL_RGBA);
		  FreeImage_Unload(dib);
		  return res;

	  }
  public:

	  virtual void  onInitGL()
	  {
		  glClearColor(0.0f,0.0f,0.0f,1.0f);

		  glEnable(GL_TEXTURE_2D);
		  glMatrixMode(GL_PROJECTION);
		  glLoadIdentity();
		  gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		  _texture   =   createTextureFromImage("floor.bmp");
		  //以上针对主OpenGL对象的————————————————

		  _fbo.setup(640,480);
		  _textureId = createTexture(_fbo._width,_height,0,GL_RGBA);
	  }
	  virtual void    onShutdownGL()
	  {
	  }
	  //绘制
	  void  renderCube(GLuint tex,bool rot) 
	  {
		  glMatrixMode(GL_PROJECTION);
		  glLoadIdentity();
		  gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		  glMatrixMode(GL_MODELVIEW);
		  glLoadIdentity();
		  glTranslatef(0.0f,0.0f,-5);

		  static float angle  =  0;
		  if (rot)
		  {
			  glRotated(angle,1,1,1);
			  angle += 1;
		  }

		  glBindTexture(GL_TEXTURE_2D,tex);
		  Vertex g_cubeVertices[] =
		  {
			  { -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			  { 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			  { 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			  { -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			  { -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			  { -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			  { 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			  { 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			  { -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			  { -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			  { 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			  { 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			  { -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			  { 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			  { 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			  { -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			  { 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			  { 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			  { 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			  { 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			  { -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			  { -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			  { -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			  { -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		  };


		  glEnableClientState(GL_VERTEX_ARRAY);
		  glEnableClientState(GL_COLOR_ARRAY);
		  glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		  float* addrVertex = (float*)g_cubeVertices;
		  float* uvAddress = (float*)&g_cubeVertices[0].u;
		  float* colorAddress = (float*)&g_cubeVertices[0].r;


		  //顶点 颜色 纹理
		  glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		  glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		  glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		  glDrawArrays(GL_QUADS,0,24);

		  glDisableClientState(GL_VERTEX_ARRAY);
		  glDisableClientState(GL_COLOR_ARRAY);
	  }

	  bool save(int w,int h,char* data,size_t length)//length可以不给
	  {
		  FIBITMAP* bitmap = FreeImage_Allocate(w,h,32,0,0,0);//32bit

		  BYTE*  pixels = (BYTE*)FreeImage_GetBits(bitmap);//存储数据的内存地址

		  memcpy(pixels,data,w * h * 4);//拷贝数据
		  bool bSuccess = FreeImage_Save(FIF_PNG,bitmap,"D:\picture.PNG",PNG_DEFAULT);
		  FreeImage_Unload(bitmap);

		  return bSuccess;
	  }

	  virtual void render(void)
	  {

		  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		  renderCube(_texture,false);

		  RECT rect;//当前窗口
		  GetClientRect(_hWnd,&rect);
		  int  w = rect.right  -  rect.left;
		  int  h = rect.bottom  -  rect.top;
		  unsigned char* data= new unsigned char[w * h *4];//4通道
		  memset(data,0,w * h * 4);
		  glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,data);//读出当前屏幕内容,只能是GL_RGBA

		  save(w,h,(char*)data,w * h *4);
		  delete []data;

	  }

  };

  int WINAPI WinMain( 
	  HINSTANCE hInstance, 
	  HINSTANCE hPrevInstance, 
	  LPSTR lpCmdLine, 
	  int nCmdShow
	  )
  {

	  FBOWindow    context;
	  context.main(640,480);
	  return  0;
  }
  • 运行:
读取屏幕数据保存成文件

















  • 从PBO读出存入文件
//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   FBOWindow :public OpenGLWindow
{
public:
	GLuint              _texture;
	FrameBufferObject   _fbo;
	GLuint              _textureId;//用于存储FrameBuffer绘制的结果

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————

		_fbo.setup(640,480);
		_textureId = createTexture(_fbo._width,_height,0,GL_RGBA);
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle  =  0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			angle += 1;
		}

		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	bool save(int w,int h,char* data,size_t length)//length可以不给
	{
		FIBITMAP* bitmap = FreeImage_Allocate(w,h,32,0,0,0);//32bit

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(bitmap);//存储数据的内存地址

		memcpy(pixels,data,w * h * 4);//拷贝数据
		bool bSuccess = FreeImage_Save(FIF_PNG,bitmap,"D:\picture1.PNG",PNG_DEFAULT);
		FreeImage_Unload(bitmap);

		return bSuccess;
	}

	virtual void render(void)
	{
		_fbo.begin(_textureId);

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		renderCube(_texture,true);
		
		RECT rect;//当前窗口
		GetClientRect(_hWnd,&rect);
		int  w = rect.right  -  rect.left;
		int  h = rect.bottom  -  rect.top;
		unsigned char* data= new unsigned char[_fbo._width * _fbo._height *4];//4通道
		memset(data,0,w * h * 4);
		glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,data);//读出当前屏幕内容,只能是GL_RGBA

		save(w,h,(char*)data,w * h *4);
		delete []data;
		
		_fbo.end ();

	
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	FBOWindow    context;
	context.main(640,480);
	return  0;
}
  • 运行:
从PBO读出存入文件

















  • 从PBuffer读出放入文件
//创建对象 传送数据 销毁对象
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "PixelBuffer.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   PBOWindow :public OpenGLWindow
{
public:
	GLuint         _texture;
	PixelBuffer    _pbuffer;
	GLuint         _dynamic;

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————
		_pbuffer.setup(_hWnd,_hDC,_hRC,640,480);
		glEnable(GL_TEXTURE_2D);
		_dynamic   =   createTexture(_pbuffer._width,_pbuffer._height,0,GL_RGBA);
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle = 0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			++angle;
		}
		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	bool save(int w,int h,char* data,size_t length)//length可以不给
	{
		FIBITMAP* bitmap = FreeImage_Allocate(w,h,32,0,0,0);//32bit

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(bitmap);//存储数据的内存地址

		memcpy(pixels,data,w * h * 4);//拷贝数据
		bool bSuccess = FreeImage_Save(FIF_PNG,bitmap,"D:\picture2.PNG",PNG_DEFAULT);
		FreeImage_Unload(bitmap);

		return bSuccess;
	}

	virtual void render(void)
	{
		_pbuffer.makeCurrent();

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		//glEnable(GL_DEPTH_TEST);       
		renderCube(_texture,true);
		RECT rect;//当前窗口
		GetClientRect(_hWnd,&rect);
		int  w = _pbuffer._width;
		int  h = _pbuffer._height;
		unsigned char* data= new unsigned char[_pbuffer._width * _pbuffer._height *4];//4通道
		memset(data,0,w * h * 4);
		glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,data);//读出当前屏幕内容,只能是GL_RGBA

		save(w,h,(char*)data,w * h *4);
		delete []data;

		
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	PBOWindow    context;
	context.main(640,480);
	return  0;
}
  • 运行:
读PBuffer写入文件

















1月31日

  • Pixel Buffer Object实现快速回读显存数据
//显存-->_pbo-->内存
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   FBOWindow :public OpenGLWindow
{
public:
	GLuint              _texture;
	GLuint              _pbo;

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————

		glGenBuffers(1,&_pbo);
	    glBindBuffer(GL_PIXEL_PACK_BUFFER,_pbo);//指定_pbo是存储像素的;GL_PIXEL_PACK_BUFFER从显卡读取数据
		glBufferData(GL_PIXEL_PACK_BUFFER,_width * _height *4,0,GL_STREAM_READ);//指定数据大小,分配显存空间
	    glBindBuffer(GL_PIXEL_PACK_BUFFER,0);//恢复状态
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle  =  0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			angle += 1;
		}

		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	bool save(int w,int h,char* data,size_t length)//length可以不给
	{
		FIBITMAP* bitmap = FreeImage_Allocate(w,h,32,0,0,0);//32bit

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(bitmap);//存储数据的内存地址

		memcpy(pixels,data,w * h * 4);//拷贝数据
		bool bSuccess = FreeImage_Save(FIF_PNG,bitmap,"D:\pbo.PNG",PNG_DEFAULT);
		FreeImage_Unload(bitmap);

		return bSuccess;
	}
	virtual void render(void)
	{

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		glEnable(GL_DEPTH_TEST);
		renderCube(_texture,false);
        //!DMA完成,不消耗CPU时间
		glBindBuffer(GL_PIXEL_PACK_BUFFER,_pbo);
		glReadPixels(0,0,_width,_height,GL_RGBA,GL_UNSIGNED_BYTE,0);//将数据从显存读入_pbo

	    void*   data   =   glMapBuffer(GL_PIXEL_PACK_BUFFER,GL_READ_ONLY);//将_pbo内容拷贝到内存中
	    if (data)
	    {
			save(_width,_height,(char*)data,_width * _height * 4);
	    }
		
		glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	FBOWindow    context;
	context.main(640,480);
	return  0;
}
_pbo在创建时,显存和内存分别有一份
读的是RGB,window下显示的是BGR
  • 运行:
PBO-BACK
PBO-存成文件形式































2月1日

  • 双PBuffer优化性能:
OpenGL默认有两个缓冲区,调用glReadPixels()时,可以指定从哪个缓冲区读数据,用下面语句
glReadBuffer(GL_FRONT);//前面用来显示
glReadBuffer(GL_BACK);//后面用来绘制
建议读前面的缓冲区(前面第一帧可能读不到数据)
//显存-->_pbo-->内存
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   FBOWindow :public OpenGLWindow
{
public:
	GLuint              _texture;
	GLuint              _pbo[2];
    int                 _DMA;
	int                 _READ;
   FBOWindow()
   {
        _DMA   =   0;//当前DMA读的
		_READ  =   1;
   }

public:
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————

		glGenBuffers(2,_pbo);
	    glBindBuffer(GL_PIXEL_PACK_BUFFER,_pbo[0]);//指定_pbo是存储像素的;GL_PIXEL_PACK_BUFFER从显卡读取数据
		glBufferData(GL_PIXEL_PACK_BUFFER,_width * _height *4,0,GL_STREAM_READ);//指定数据大小,分配显存空间
	   

		glBindBuffer(GL_PIXEL_PACK_BUFFER,_pbo[1]);//指定_pbo是存储像素的;GL_PIXEL_PACK_BUFFER从显卡读取数据
		glBufferData(GL_PIXEL_PACK_BUFFER,_width * _height *4,0,GL_STREAM_READ);//指定数据大小,分配显存空间
		glBindBuffer(GL_PIXEL_PACK_BUFFER,0);//恢复状态
	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle  =  0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			angle += 1;
		}

		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	bool save(int w,int h,char* data,size_t length)//length可以不给
	{
		FIBITMAP* bitmap = FreeImage_Allocate(w,h,32,0,0,0);//32bit

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(bitmap);//存储数据的内存地址

		memcpy(pixels,data,w * h * 4);//拷贝数据
		bool bSuccess = FreeImage_Save(FIF_PNG,bitmap,"D:\pbo2.PNG",PNG_DEFAULT);
		FreeImage_Unload(bitmap);

		return bSuccess;
	}
	virtual void render(void)
	{

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		glEnable(GL_DEPTH_TEST);
		renderCube(_texture,true);
        //!DMA完成,不消耗CPU时间(将后台数据拷贝到pbo)
		glBindBuffer(GL_PIXEL_PACK_BUFFER,_pbo[_DMA]);
		glReadPixels(0,0,_width,_height,GL_RGBA,GL_UNSIGNED_BYTE,0);//将数据从显存读入_pbo

		glBindBuffer(GL_PIXEL_PACK_BUFFER,_pbo[_READ]);
	    void*   data   =   glMapBuffer(GL_PIXEL_PACK_BUFFER,GL_READ_ONLY);//将_pbo内容拷贝到内存中
	    if (data)
	    {
			save(_width,_height,(char*)data,_width * _height * 4);
	    }
		
		glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
		 
		std::swap(_DMA,_READ);//乒乓球技术
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	FBOWindow    context;
	context.main(640,480);
	return  0;
}
  • 运行:













  • 存成文件:
PBO双缓冲

















  • 快速回读显存数据(从内存写到显卡)
//内存-->_pbo-->显存
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   PBOUnPackWindow :public OpenGLWindow
{
public:
	GLuint              _texture;
	GLuint              _dynamicTex;
	GLuint              _pbo[2];
	int                 _DMA;
	int                 _WRITE;
	PBOUnPackWindow()
	{
		_DMA   =   0;//当前DMA读的
		_WRITE  =   1;
	}
public:
	//动态更新Buffer数据
	void updateBuffer(int w,int h,unsigned char* data)
	{
		int*  iData = (int*)data;
		for (int i = 0;i < w * h;++i)
		{
			iData[i]  =  rand() * rand();
		}
	}
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————

		glGenBuffers(2,_pbo);
		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,_pbo[0]);//指定_pbo是存储像素的;GL_PIXEL_PACK_BUFFER从显卡读取数据
		glBufferData(GL_PIXEL_UNPACK_BUFFER,_width * _height *4,0,GL_STREAM_DRAW);//指定数据大小,分配显存空间

		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,_pbo[1]);//指定_pbo是存储像素的;GL_PIXEL_PACK_BUFFER从显卡读取数据
		glBufferData(GL_PIXEL_UNPACK_BUFFER,_width * _height *4,0,GL_STREAM_DRAW);//指定数据大小,分配显存空间
		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,0);//恢复状态

		_dynamicTex = createTexture(_width,_height,0,GL_RGBA);

	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle  =  0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			angle += 1;
		}

		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	bool save(int w,int h,char* data,size_t length)//length可以不给
	{
		FIBITMAP* bitmap = FreeImage_Allocate(w,h,32,0,0,0);//32bit

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(bitmap);//存储数据的内存地址

		memcpy(pixels,data,w * h * 4);//拷贝数据
		bool bSuccess = FreeImage_Save(FIF_PNG,bitmap,"D:\pbo2.PNG",PNG_DEFAULT);
		FreeImage_Unload(bitmap);

		return bSuccess;
	}
	virtual void render(void)
	{

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		glEnable(GL_DEPTH_TEST);
		//renderCube(_texture,true);
		//!纹理数据 from _pbo 通过DMA to texture
		glBindTexture(GL_TEXTURE_2D,_dynamicTex);

		//通过DMA处理
		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,_pbo[_DMA]);
		glTexSubImage2D(GL_TEXTURE_2D,0,0,0,_width,_height,GL_RGBA,GL_UNSIGNED_BYTE,0);

		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,_pbo[_WRITE]);
		void*   data   =   glMapBuffer(GL_PIXEL_UNPACK_BUFFER,GL_WRITE_ONLY);//将_pbo内容拷贝到内存中
		if (data)
		{
			updateBuffer(_width,_height,(unsigned char *)data);
		}

		glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);

		glBindBuffer(GL_PIXEL_UNPACK_BUFFER,0);
		renderCube(_dynamicTex,true);


		std::swap(_DMA,_WRITE);//乒乓球技术
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	PBOUnPackWindow    context;
	context.main(640,480);
	return  0;
}
  • 运行:













2月2日

总结:
FBO对OpenGL的版本要求很高,实现离屏渲染、画中画
做视频的播放,建议用FBO的双缓冲
做视频的录制和获取,建议用FBO的双缓冲来读取显卡内容到内存
  • 显卡版本低,高效实现画中画效果
//最慢的方式实现画中画
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   WindowWin :public OpenGLWindow
{
public:
	GLuint              _texture;
	GLuint              _dynamicTex;

	WindowWin()
	{
		
	}
public:
	
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————


		_dynamicTex = createTexture(_width,_height,0,GL_RGBA);

	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle  =  0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			angle += 1;
		}

		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}

	virtual void render(void)
	{

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		glEnable(GL_DEPTH_TEST);
		renderCube(_texture,true);
        char* data = new char[_width * _height * 4];

		glReadPixels(0,0,_width,_height,GL_RGBA,GL_UNSIGNED_BYTE,data);//将数据读入内存
		
		glBindTexture(GL_TEXTURE_2D,_dynamicTex);
		//将屏幕内容制作成一张纹理
		glTexSubImage2D(GL_TEXTURE_2D,0,0,0,_width,_height,GL_RGBA,GL_UNSIGNED_BYTE,data);
	    delete []data;
	    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
        renderCube(_dynamicTex,false);
	}

};

int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	WindowWin    context;
	context.main(640,480);
	return  0;
}
  • 运行:
//效率稍高一点方法:
#include <windows.h>
#include <tchar.h>
#include "OpenGLWindow.h" 
#include <mmsystem.h>

#include "FreeImage.h"
#include "CELLMath.hpp"
#include "FrameBufferObject.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")

struct Vertex
{ 
	float   x,y,z;
	float   u, v;
	float   r,g,b;
};

class   WindowWin :public OpenGLWindow
{
public:
	GLuint              _texture;
	GLuint              _dynamicTex;

	WindowWin()
	{
		
	}
public:
	
	/*使用FreeImage加载图片*/
	unsigned createTexture(int w,int h,const void* data,GLenum type)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}
		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		for (int i = 0; i < width * height * 4; i += 4)
		{
			BYTE temp = pixels[i];
			pixels[i] = pixels[i + 2];
			pixels[i + 2] = temp;
		}

		unsigned res = createTexture(width,height,pixels,GL_RGBA);
		FreeImage_Unload(dib);
		return res;

	}
public:

	virtual void  onInitGL()
	{
		glClearColor(0.0f,0.0f,0.0f,1.0f);

		glEnable(GL_TEXTURE_2D);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width) / double(_height),0.1f,100.0f);
		_texture   =   createTextureFromImage("floor.bmp");
		//以上针对主OpenGL对象的————————————————


		_dynamicTex = createTexture(_width,_height,0,GL_RGBA);

	}
	virtual void    onShutdownGL()
	{
	}
	//绘制
	void  renderCube(GLuint tex,bool rot) 
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(45.0f,double(_width)/double(_height),0.1f,100.0f);//透视投影

		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-5);

		static float angle  =  0;
		if (rot)
		{
			glRotated(angle,1,1,1);
			angle += 1;
		}

		glBindTexture(GL_TEXTURE_2D,tex);
		Vertex g_cubeVertices[] =
		{
			{ -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
			{ -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

			{ 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
			{ 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

			{ -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
			{ -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
		};


		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_COLOR_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);

		float* addrVertex = (float*)g_cubeVertices;
		float* uvAddress = (float*)&g_cubeVertices[0].u;
		float* colorAddress = (float*)&g_cubeVertices[0].r;


		//顶点 颜色 纹理
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),addrVertex );
		glColorPointer(3,GL_FLOAT,sizeof(Vertex),colorAddress);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),uvAddress);

		glDrawArrays(GL_QUADS,0,24);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_COLOR_ARRAY);
	}
	virtual void render(void)
	{
		//效率高的方案:

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		glEnable(GL_DEPTH_TEST);
		renderCube(_texture,true);
		
		glBindTexture(GL_TEXTURE_2D,_dynamicTex);
		//将缓冲区内容直接拷贝到纹理上
		glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,_width,_height);
		
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);     
		renderCube(_dynamicTex,false);
	}

};
int WINAPI WinMain( 
				   HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPSTR lpCmdLine, 
				   int nCmdShow
				   )
{

	WindowWin    context;
	context.main(640,480);
	return  0;
}
  • 运行:

同上面运行结果

2月4日

  • 第6章 场景控制
  • 三维的理论
世界坐标:描述整个世界,中心点在0,0,0位置上,无限大,没有单位。且是始终不变的。你面对屏幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。
世界坐标

















局部坐标:在场景中的一颗树,一个人物,一个建筑都是由很多三角面组成,即模型是由很多个三维点组成,这些点的位置是相对模型自己。
观察矩阵:就是我们常说的照相机(人的眼睛),照相机在什么位置上看世界。
投影变换:目的是确定3D空间的物体如何投影到2D平面上,从而形成2D图像,这些2D图像再经视口变换就被渲染到屏幕上。前面提到投影变换有两种:正交投影和透视投影。透视投影用的比较广泛,它与真实世界更相近:近处的物体看起来要比远处的物体大;而正交投影没有这个效果,正交投影通常用于CAD或建筑设计。下面是正交投影与透视投影效果示意图: 
投影变换














2月5日

  • 最基本的摄像机
OpenGL里并没有提供摄像机的一个接口,但是可以通过对矩阵的控制来实现摄像机
//lesson206.cpp
//加载外部的图片作为纹理
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int
	//控制摄像机
	float3 _eye;
	float3 _lookAt;//往哪一点看
public:
	SamplerTexture() 
	{
		_eye     =  float3(0,0,10);
		_lookAt  =  float3(0,0,0);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},
		};

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();

		gluLookAt(_eye.x,_eye.y,_eye.z,_lookAt.x,_lookAt.y,_lookAt.z,0,1,0);//实现摄像机的控制

		glTranslatef(0,0,0);

		static float angle =0;
		glRotated(angle,1,1,1);
		angle += 0.5;

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
					break;
				case VK_RIGHT:
					break;
				case VK_UP:
					_eye.z -= 0.1f;
					break;
				case VK_DOWN:
					_eye.z += 0.1f;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













2月6日

  • 对摄像机控制-键盘控制摄像机移动
//lesson206.cpp
//摄像机围绕物体旋转
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int
	
	GLuint _texGround;
	
	//控制摄像机
	float3 _eye;
	float3 _lookAt;//往哪一点看
public:
	SamplerTexture() 
	{
		_eye     =  float3(0,0,10);
		_lookAt  =  float3(0,0,0);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

        float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};
     

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();


        static float angle = 0;
		float r = 10;
        _eye.x = cos(angle* M_PI/180)*r;
        _eye.z = sin(angle* M_PI/180)*r;
        angle += 0.1;

		gluLookAt(_eye.x,_eye.y,_eye.z,_lookAt.x,_lookAt.y,_lookAt.z,0,1,0);//实现摄像机的控制

		glTranslatef(0,0,0);

		//static float angle =0;
		//glRotated(angle,1,1,1);
		//angle += 0.5;

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
        //清成单位矩阵
      //  glLoadIdentity();//地面不动
        glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
                    _eye.x += 1;
					break;
				case VK_RIGHT:
                    _eye.x -= 1;
					break;
				case VK_UP:
					_eye.z -= 0.1f;
					break;
				case VK_DOWN:
					_eye.z += 0.1f;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













2月7日

  • 第一人称摄像机类封装
//camera.h
#pragma once

#include "CELLMath.hpp"
using namespace CELL;
class Camera
{
public:
    float3 _eye;//中心点
	float3  _lookat;

	float3  _up;//定义了摄像机的y轴
	float3  _right;//定义了摄像机的x轴
	//不用定义z轴,x,y叉积是z(_eye和 _lookat形成的刚好是z轴)
	float   _speed;
	Camera(void)
	{
       _eye    =  float3(0,0,10);
	   _lookat =  float3(0,0,0);
	   _up     =  float3(0,1,0);
	   _right  =  float3(1,0,0);
	   _speed  =  0.2f;
	}

	void  moveLeft()
	{
		_eye     -=  normalize(_right)* _speed ;//normalize(_right)将_right单位化
	    _lookat  -=  normalize(_right)* _speed ;
	}
	void  moveRight()
	{
		_eye    +=  normalize(_right)* _speed ;
	    _lookat +=  normalize(_right)* _speed ;
	}
	void  moveFront()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     += dir * _speed;
		_lookat  += dir * _speed;
	}
	void  moveBack()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     -= dir * _speed;
        _lookat  -= dir * _speed;
	}

	void  update()
	{
       gluLookAt(_eye.x,_eye.y,_eye.z,_lookat.x,_lookat.y,_lookat.z,_up.x,_up.y,_up.z);
	}

	virtual ~Camera(void)
	{
	}
};
//lesson206.cpp
//摄像机围绕物体旋转
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int
	
	GLuint _texGround;

	Camera _camera;
	
public:
	SamplerTexture() 
	{
	
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

        float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};
     

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();
        //摄像机更新
        _camera.update();

		glTranslatef(0,0,0);

		//static float angle =0;
		//glRotated(angle,1,1,1);
		//angle += 0.5;

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
        //清成单位矩阵
      //  glLoadIdentity();//地面不动
        glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
                    _camera.moveLeft();
					break;
				case VK_RIGHT:
                    _camera.moveRight();
					break;
				case VK_UP:
					_camera.moveFront();
					break;
				case VK_DOWN:
					_camera.moveBack();
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













2月8日

  • 第一人称摄像机类封装-增加鼠标操作
//Camera.h
#pragma once

#include "CELLMath.hpp"
using namespace CELL;
class Camera
{
public:
    float3 _eye;//中心点
	float3  _lookat;

	float3  _up;//定义了摄像机的y轴
	float3  _right;//定义了摄像机的x轴
	//不用定义z轴,x,y叉积是z(_eye和 _lookat形成的刚好是z轴)
	float   _speed;
	Camera(void)
	{
       _eye    =  float3(0,0,10);
	   _lookat =  float3(0,0,0);
	   _up     =  float3(0,1,0);
	   _right  =  float3(1,0,0);
	   _speed  =  0.2f;
	}

	void  moveLeft()
	{
		_eye     -=  normalize(_right)* _speed ;//normalize(_right)将_right单位化
	    _lookat  -=  normalize(_right)* _speed ;
	}
	void  moveRight()
	{
		_eye    +=  normalize(_right)* _speed ;
	    _lookat +=  normalize(_right)* _speed ;
	}
	void  moveFront()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     += dir * _speed;
		_lookat  += dir * _speed;
	}
	void  moveBack()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     -= dir * _speed;
        _lookat  -= dir * _speed;
	}

	void  update()
	{
       gluLookAt(_eye.x,_eye.y,_eye.z,_lookat.x,_lookat.y,_lookat.z,_up.x,_up.y,_up.z);
	}
    void rotateY(float angle)
	{
       float3 dir  = normalize(_lookat -_eye);
	   float  len  = length(_lookat - _eye);
	   float3 dir1 = CELL::rotateY(dir,angle);//眼镜现在看的方向
	       _lookat = _eye  + dir1 * len;
	       _right  = normalize(cross(dir1 , _up));
	}
	virtual ~Camera(void)
	{
	}
};
//lesson206.cpp
//摄像机围绕物体旋转
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int
	
	GLuint _texGround;

	Camera _camera;
	int2 _mouseDown;
    bool _bDownFlag;//鼠标按下的标志
	
public:
	SamplerTexture() 
	{
	_bDownFlag  =  false;
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

        float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};
     

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();
        //摄像机更新
        _camera.update();

		glTranslatef(0,0,0);

		//static float angle =0;
		//glRotated(angle,1,1,1);
		//angle += 0.5;

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
        //清成单位矩阵
      //  glLoadIdentity();//地面不动
        glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_LBUTTONDOWN:
			{
               _bDownFlag = true;
			   _mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y
			}
           break;
		case WM_LBUTTONUP:
			{
               _bDownFlag = false;
			}
		   break;
		case WM_MOUSEMOVE:
			{
                if(_bDownFlag)
				{
                 int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
				 float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
				 _mouseDown = mouseCur;
				 _camera.rotateY(xOffset * 0.5f);
				}
			}
		   break;

			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
                    _camera.moveLeft();
					break;
				case VK_RIGHT:
                    _camera.moveRight();
					break;
				case VK_UP:
					_camera.moveFront();
					break;
				case VK_DOWN:
					_camera.moveBack();
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













  • 第三人称摄像机
//Camera3rd.h
#pragma once

#include "CELLMath.hpp"
using namespace CELL;
class Camera3rd
{
public:
    float3 _eye;//中心点
	float3  _lookat;

	float3  _up;//定义了摄像机的y轴
	float3  _right;//定义了摄像机的x轴
	//不用定义z轴,x,y叉积是z(_eye和 _lookat形成的刚好是z轴)
	float   _speed;
	float   _radius;//摄像机和角色间的半径
	Camera3rd(void)
	{
       _eye    =  float3(0,10,10);
	   _lookat =  float3(0,0,0);
       _radius =  10;
       updateLookat(_lookat);

	   _up     =  float3(0,1,0);
	   _right  =  float3(1,0,0);
	   _speed  =  0.2f;
	   
	}

	void updateLookat(float3 pos)
	{
		float3 dir = normalize(_lookat - _eye);
       _lookat  =  pos;
	   _eye     =  _lookat - _radius * dir;
	}
	void  moveLeft()
	{
		_eye     -=  normalize(_right)* _speed ;//normalize(_right)将_right单位化
	    _lookat  -=  normalize(_right)* _speed ;
	}
	void  moveRight()
	{
		_eye    +=  normalize(_right)* _speed ;
	    _lookat +=  normalize(_right)* _speed ;
	}
	void  moveFront()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     += dir * _speed;
		_lookat  += dir * _speed;
	}
	void  moveBack()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     -= dir * _speed;
        _lookat  -= dir * _speed;
	}

	void  update()
	{
       gluLookAt(_eye.x,_eye.y,_eye.z,_lookat.x,_lookat.y,_lookat.z,_up.x,_up.y,_up.z);
	}
    void rotateY(float angle)
	{
       float3 dir  = normalize(_lookat -_eye);
	   float3 dir1 = CELL::rotateY(dir,angle);//眼镜现在看的方向
	       _eye = _lookat  - dir1 * _radius;
	       _right  = normalize(cross(dir1 , _up));
	}
	virtual ~Camera3rd(void)
	{
	}
};
//lesson206.cpp
//摄像机围绕物体旋转
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int
	
	GLuint _texGround;

	Camera3rd _camera;
	int2 _mouseDown;
    bool _bDownFlag;//鼠标按下的标志
	
	float3 _rolePos;
public:
	SamplerTexture() 
	{
	_bDownFlag  =  false;
	_rolePos    =  float3(0,0,0);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

        float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};
     

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();

		_camera.updateLookat(_rolePos);
        //摄像机更新
        _camera.update();

		glPushMatrix(); 
		glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
        //清成单位矩阵
      //  glLoadIdentity();//地面不动
		glPopMatrix();
        glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_LBUTTONDOWN:
			{
               _bDownFlag = true;
			   _mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y
			}
           break;
		case WM_LBUTTONUP:
			{
               _bDownFlag = false;
			}
		   break;
		case WM_MOUSEMOVE:
			{
                if(_bDownFlag)
				{
                 int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
				 float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
				 _mouseDown = mouseCur;
				 _camera.rotateY(xOffset * 0.5f);
				}
			}
		   break;

			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
                    _rolePos.x  -=  1;
					break;
				case VK_RIGHT:
                    _rolePos.x  +=  1;
					break;
				case VK_UP:
				    _rolePos.z  -=  1;
					break;
				case VK_DOWN:
				    _rolePos.z  +=  1;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













2月9日

  • 第三人称摄像机类的完善
//Camera3rd.h
#pragma once

#include "CELLMath.hpp"
using namespace CELL;
class Camera3rd
{
public:
    float3 _eye;//中心点
	float3  _lookat;

	float3  _up;//定义了摄像机的y轴
	float3  _right;//定义了摄像机的x轴
	//不用定义z轴,x,y叉积是z(_eye和 _lookat形成的刚好是z轴)
	float   _speed;
	float   _radius;//摄像机和角色间的半径
	Camera3rd(void)
	{
       _eye    =  float3(0,10,10);
	   _lookat =  float3(0,0,0);
       _radius =  10;
       updateLookat(_lookat);

	   _up     =  float3(0,1,0);
	   _right  =  float3(1,0,0);
	   _speed  =  0.2f;
	   
	}
    float getRadius() const
	{
		return _radius;
	}

	void setRadius(float radius)
	{
		_radius = radius;
	}
	void updateLookat(float3 pos)
	{
		float3 dir = normalize(_lookat - _eye);
       _lookat  =  pos;
	   _eye     =  _lookat - _radius * dir;
	}
	void  moveLeft()
	{
		_eye     -=  normalize(_right)* _speed ;//normalize(_right)将_right单位化
	    _lookat  -=  normalize(_right)* _speed ;
	}
	void  moveRight()
	{
		_eye    +=  normalize(_right)* _speed ;
	    _lookat +=  normalize(_right)* _speed ;
	}
	void  moveFront()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     += dir * _speed;
		_lookat  += dir * _speed;
	}
	void  moveBack()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     -= dir * _speed;
        _lookat  -= dir * _speed;
	}

	void  update()
	{
       gluLookAt(_eye.x,_eye.y,_eye.z,_lookat.x,_lookat.y,_lookat.z,_up.x,_up.y,_up.z);
	}
    void rotateY(float angle)
	{
       float3 dir  = normalize(_lookat -_eye);
	   float3 dir1 = CELL::rotateY(dir,angle);//眼镜现在看的方向
	       _eye = _lookat  - dir1 * _radius;
	       _right  = normalize(cross(dir1 , _up));
	}
	virtual ~Camera3rd(void)
	{
	}
};
//lesson206.cpp
//摄像机围绕物体旋转
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int
	
	GLuint _texGround;

	Camera3rd _camera;
	int2 _mouseDown;
    bool _bDownFlag;//鼠标按下的标志
	
	float3 _rolePos;
public:
	SamplerTexture() 
	{
	_bDownFlag  =  false;
	_rolePos    =  float3(0,0,0);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		glMatrixMode(GL_PROJECTION);//矩阵模式要操作投影矩阵
		glLoadIdentity();//将投影矩阵清空成单位矩阵

		gluPerspective(60,double(_width)/double(_height),0.1,1000);

        float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};
     

		glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		glLoadIdentity();

		_camera.updateLookat(_rolePos);
        //摄像机更新
        _camera.update();

		glPushMatrix(); 
		glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
        //清成单位矩阵
      //  glLoadIdentity();//地面不动
		glPopMatrix();
        glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_LBUTTONDOWN:
			{
               _bDownFlag = true;
			   _mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y
			}
           break;
		case WM_LBUTTONUP:
			{
               _bDownFlag = false;
			}
		   break;
		case WM_MOUSEWHEEL:
			{
               int delta = (short)HIWORD(wParam);//鼠标滚动过的距离(120的整数倍,正的即正向滚动)
			   if (delta > 0)
			   {
				   _camera.setRadius(_camera.getRadius() * 1.2f);
			   }
			   else
			   {
                   _camera.setRadius(_camera.getRadius() * 0.8f);
			   }
			}
		case WM_MOUSEMOVE:
			{
                if(_bDownFlag)
				{
                 int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
				 float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
				 _mouseDown = mouseCur;
				 _camera.rotateY(xOffset * 0.5f);
				}
			}
		   break;

			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
                    _rolePos.x  -=  1;
					break;
				case VK_RIGHT:
                    _rolePos.x  +=  1;
					break;
				case VK_UP:
				    _rolePos.z  -=  1;
					break;
				case VK_DOWN:
				    _rolePos.z  +=  1;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













  • 第三人称摄像机的重新设计(升级,camera类不再依赖OpenGL实现,取消对glu的依赖)
//Camera3rd.h
#pragma once

#include "CELLMath.hpp"
using namespace CELL;
class Camera3rd
{
public:
    float3 _eye;//中心点
	float3  _lookat;

	float3  _up;//定义了摄像机的y轴
	float3  _right;//定义了摄像机的x轴
	//不用定义z轴,x,y叉积是z(_eye和 _lookat形成的刚好是z轴)
	float   _speed;
	float   _radius;//摄像机和角色间的半径
	
	matrix4 _matView;
	matrix4 _matProj;//投影
	Camera3rd(void)
	{
       _eye    =  float3(0,10,10);
	   _lookat =  float3(0,0,0);
       _radius =  10;
       updateLookat(_lookat);

	   _up     =  float3(0,1,0);
	   _right  =  float3(1,0,0);
	   _speed  =  0.2f;
	   
	}
    float getRadius() const
	{
		return _radius;
	}

	void setRadius(float radius)
	{
		_radius = radius;
	}
 
	matrix4 getMVP()
	{
        return _matProj * _matView;//观察矩阵*投影矩阵
	}

	void perspective(float fovy, float aspect, float zNear, float zFar)
	{
		_matProj = CELL::perspective(fovy,aspect,zNear,zFar);//角度 宽高比 
	}
	void updateLookat(float3 pos)
	{
		float3 dir = normalize(_lookat - _eye);
       _lookat  =  pos;
	   _eye     =  _lookat - _radius * dir;
	}
	void  moveLeft()
	{
		_eye     -=  normalize(_right)* _speed ;//normalize(_right)将_right单位化
	    _lookat  -=  normalize(_right)* _speed ;
	}
	void  moveRight()
	{
		_eye    +=  normalize(_right)* _speed ;
	    _lookat +=  normalize(_right)* _speed ;
	}
	void  moveFront()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     += dir * _speed;
		_lookat  += dir * _speed;
	}
	void  moveBack()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     -= dir * _speed;
        _lookat  -= dir * _speed;
	}

	void  update()
	{
	   _matView  =  lookAt(_eye,_lookat,_up);//解除对gluLookAt的依赖 
      // gluLookAt(_eye.x,_eye.y,_eye.z,_lookat.x,_lookat.y,_lookat.z,_up.x,_up.y,_up.z);
	}
    void rotateY(float angle)
	{
       float3 dir  = normalize(_lookat -_eye);
	   float3 dir1 = CELL::rotateY(dir,angle);//眼镜现在看的方向
	       _eye = _lookat  - dir1 * _radius;
	       _right  = normalize(cross(dir1 , _up));
	}
	virtual ~Camera3rd(void)
	{
	}
};
//lesson206.cpp
//摄像机围绕物体旋转
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int
	
	GLuint _texGround;

	Camera3rd _camera;
	int2 _mouseDown;
    bool _bDownFlag;//鼠标按下的标志
	
	float3 _rolePos;
public:
	SamplerTexture() 
	{
	_bDownFlag  =  false;
	_rolePos    =  float3(0,0,0);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)
		

        float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};
     

		//glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
      //指定模型矩阵-产生投影矩阵-产生观察矩阵-将观察矩阵*投影矩阵当成模型矩阵
		//glLoadIdentity();

		glMatrixMode(GL_MODELVIEW);//矩阵模式要操作投影矩阵
		//glLoadIdentity();//将投影矩阵清空成单位矩阵

		_camera.perspective(60,float(_width)/float(_height),0.1f,1000.0f);
		//gluPerspective(60,double(_width)/double(_height),0.1,1000);
		

		_camera.updateLookat(_rolePos);
        //摄像机更新
        _camera.update();

		matrix4 matVP  =  _camera.getMVP();
        glLoadMatrixf(matVP.data());

		//glLoadMatrixf(_camera._matView.data());
		//glPushMatrix(); 
		glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
        //清成单位矩阵
      //  glLoadIdentity();//地面不动
		//glPopMatrix();
		glLoadMatrixf(matVP.data());

        glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_LBUTTONDOWN:
			{
               _bDownFlag = true;
			   _mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y
			}
           break;
		case WM_LBUTTONUP:
			{
               _bDownFlag = false;
			}
		   break;
		case WM_MOUSEWHEEL:
			{
               int delta = (short)HIWORD(wParam);//鼠标滚动过的距离(120的整数倍,正的即正向滚动)
			   if (delta > 0)
			   {
				   _camera.setRadius(_camera.getRadius() * 1.2f);
			   }
			   else
			   {
                   _camera.setRadius(_camera.getRadius() * 0.8f);
			   }
			}
		case WM_MOUSEMOVE:
			{
                if(_bDownFlag)
				{
                 int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
				 float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
				 _mouseDown = mouseCur;
				 _camera.rotateY(xOffset * 0.5f);
				}
			}
		   break;

			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
                    _rolePos.x  -=  1;
					break;
				case VK_RIGHT:
                    _rolePos.x  +=  1;
					break;
				case VK_UP:
				    _rolePos.z  -=  1;
					break;
				case VK_DOWN:
				    _rolePos.z  +=  1;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行同前一节

2月16日

  • 摄像机的应用-多摄像机切换控制
//lesson206.cpp
//新增功能:投影转化
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int

	GLuint _texGround;

	Camera3rd _camera;
	int2 _mouseDown;
	bool _bDownFlag;//鼠标按下的标志

	float3 _rolePos;
	float3 _moveTo;
public:
	SamplerTexture() 
	{
		_bDownFlag  =  false;
		_rolePos    =  float3(0,0,0);
		_moveTo     =  _rolePos;
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)

		float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

			//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};


		//glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		//指定模型矩阵-产生投影矩阵-产生观察矩阵-将观察矩阵*投影矩阵当成模型矩阵
		//glLoadIdentity();

		glMatrixMode(GL_MODELVIEW);//矩阵模式要操作投影矩阵
		//glLoadIdentity();//将投影矩阵清空成单位矩阵

		_camera.perspective(60,float(_width)/float(_height),0.1f,1000.0f);
		//gluPerspective(60,double(_width)/double(_height),0.1,1000);

		float3 dir = normalize(_moveTo - _rolePos);//得到移动的方向

		if (length(_moveTo - _rolePos) < 1)
		{
			_rolePos = _moveTo;
		}
		else 
		{
			_rolePos += dir * 1.0f/60.0f;
		}
		_camera.updateLookat(_rolePos);
		//摄像机更新
		_camera.update();

		matrix4 matVP  =  _camera.getMVP();
		glLoadMatrixf(matVP.data());

		//glLoadMatrixf(_camera._matView.data());
		//glPushMatrix(); 
		glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
		//清成单位矩阵
		//  glLoadIdentity();//地面不动
		//glPopMatrix();
		glLoadMatrixf(matVP.data());

		glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_SIZE://窗口大小变化
			{
				if(::IsWindow(hWnd))
				{
					//获取窗口宽高
					RECT rt;
					GetClientRect(_hWnd,&rt);
					int w = rt.right - rt.left;
					int h = rt.bottom - rt.top;
					glViewport(0,0,w,h);//指定视口
					//把屏幕坐标转化成世界坐标
					_camera.setView(w,h);
				}
			}
			break;
		case WM_LBUTTONDOWN:
			{
				_bDownFlag = true;
				_mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y

				CELL::Ray ray = _camera.createRayFromScreen(_mouseDown.x,_mouseDown.y);
				float3   orth = ray.getOrigin();
				float    tm   = (orth.y - (-1))/ray.getDirection().y;//多长时间到达地面
				float3   c    = ray.getOrigin() + abs(tm) * ray.getDirection();
				_moveTo = c;
			}
			break;
		case WM_LBUTTONUP:
			{
				_bDownFlag = false;
			}
			break;
		case WM_MOUSEWHEEL:
			{
				int delta = (short)HIWORD(wParam);//鼠标滚动过的距离(120的整数倍,正的即正向滚动)
				if (delta > 0)
				{
					_camera.setRadius(_camera.getRadius() * 1.2f);
				}
				else
				{
					_camera.setRadius(_camera.getRadius() * 0.8f);
				}
			}
		case WM_MOUSEMOVE:
			{
				if(_bDownFlag)
				{
					int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
					float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
					_mouseDown = mouseCur;
					_camera.rotateY(xOffset * 0.5f);
				}
			}
			break;

			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
					_rolePos.x  -=  1;
					break;
				case VK_RIGHT:
					_rolePos.x  +=  1;
					break;
				case VK_UP:
					_rolePos.z  -=  1;
					break;
				case VK_DOWN:
					_rolePos.z  +=  1;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
#pragma once

#include "CELLMath.hpp"
using namespace CELL;


class Camera3rd
{
public:
	float3 _eye;//中心点
	float3  _lookat;

	float3  _up;//定义了摄像机的y轴
	float3  _right;//定义了摄像机的x轴
	//不用定义z轴,x,y叉积是z(_eye和 _lookat形成的刚好是z轴)
	float   _speed;
	float   _radius;//摄像机和角色间的半径

	matrix4 _matView;
	matrix4 _matProj;//投影
	float2  _viewSize;

public:
	Camera3rd(void)
	{
		_eye    =  float3(0,10,10);
		_lookat =  float3(0,0,0);
		_radius =  10;
		updateLookat(_lookat);

		_up     =  float3(0,1,0);
		_right  =  float3(1,0,0);
		_speed  =  0.2f;

	}
	float getRadius() const
	{
		return _radius;
	}

	void setRadius(float radius)
	{
		_radius = radius;
	}
	void setView(int x,int y)
	{
		_viewSize.x = x;
		_viewSize.y = y;
	}

	matrix4 getMVP()
	{
		return _matProj * _matView;//观察矩阵*投影矩阵
	}

	void perspective(float fovy, float aspect, float zNear, float zFar)
	{
		_matProj = CELL::perspective(fovy,aspect,zNear,zFar);//角度 宽高比 
	}
	void updateLookat(float3 pos)
	{
		float3 dir = normalize(_lookat - _eye);
		_lookat  =  pos;
		_eye     =  _lookat - _radius * dir;
	}

	//窗口坐标转化为世界坐标
	bool unProject(const float4& screen,float4& world)
	{
		float4 v;
		v.x = screen.x;
		v.y = screen.y;
		v.z = screen.z;
		v.w = 1.0;

		v.x = (v.x) / _viewSize.x;
		v.y = (_viewSize.y - v.y) /_viewSize.y;

		v.x = v.x * 2.0f - 1.0f;
		v.y = v.y * 2.0f - 1.0f;
		v.z = v.z * 2.0f - 1.0f;

		CELL::matrix4 inverse = (_matProj * _matView).inverse();

		v = v *inverse;
		if(v.w == 0.0f)
		{
			return false;
		}
		world = v / v.w;
		return true;
	}
	//根据鼠标给定的位置创建射线
	Ray createRayFromScreen(int x,int y)
	{
		float4 minWorld;
		float4 maxWorld;

		float4 screen(float(x),float(y),0,1);
		float4 screen1(float(x),float(y),1,1);

		unProject(screen,minWorld);
		unProject(screen1,maxWorld);
		Ray ray;
		ray.setOrigin(float3(minWorld.x,minWorld.y,minWorld.z));

		float3 dir(maxWorld.x - minWorld.x,maxWorld.y - minWorld.y,maxWorld.z - minWorld.z);
		ray.setDirection(normalize(dir));

		return ray;
	}

	void  moveLeft()
	{
		_eye     -=  normalize(_right)* _speed ;//normalize(_right)将_right单位化
		_lookat  -=  normalize(_right)* _speed ;
	}
	void  moveRight()
	{
		_eye    +=  normalize(_right)* _speed ;
		_lookat +=  normalize(_right)* _speed ;
	}
	void  moveFront()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     += dir * _speed;
		_lookat  += dir * _speed;
	}
	void  moveBack()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     -= dir * _speed;
		_lookat  -= dir * _speed;
	}

	void  update()
	{
		_matView  =  lookAt(_eye,_lookat,_up);//解除对gluLookAt的依赖 
		// gluLookAt(_eye.x,_eye.y,_eye.z,_lookat.x,_lookat.y,_lookat.z,_up.x,_up.y,_up.z);
	}
	void rotateY(float angle)
	{
		float3 dir  = normalize(_lookat -_eye);
		float3 dir1 = CELL::rotateY(dir,angle);//眼镜现在看的方向
		_eye = _lookat  - dir1 * _radius;
		_right  = normalize(cross(dir1 , _up));
	}
	virtual ~Camera3rd(void)
	{
	}
};

2月18日

  • 摄像机路径动画-曲线飞行的摄像机
//lesson206.cpp
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include "Camera.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int

	GLuint _texGround;

	Camera _camera[3];
	int2 _mouseDown;
	bool _bDownFlag;//鼠标按下的标志

    int _cameraIndex;

	float3 _rolePos;
	float3 _moveTo;
public:
	SamplerTexture() 
	{
		_bDownFlag  =  false;
		_rolePos    =  float3(0,0,0);
		_moveTo     =  _rolePos;
		_cameraIndex=  0;

		_camera[0]._eye    =  float3(0,10,10);
		_camera[0]._lookat =  float3(0,0,0);

		_camera[1]._eye    =  float3(10,0,10);
		_camera[1]._lookat =  float3(-10,0,-10);

		_camera[2]._eye    =  float3(10,10,10);
		_camera[2]._lookat =  float3(-10,0,-10);
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)

		float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

			//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};


		//glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		//指定模型矩阵-产生投影矩阵-产生观察矩阵-将观察矩阵*投影矩阵当成模型矩阵
		//glLoadIdentity();

		glMatrixMode(GL_MODELVIEW);//矩阵模式要操作投影矩阵
		//glLoadIdentity();//将投影矩阵清空成单位矩阵

		_camera[_cameraIndex].perspective(60,float(_width)/float(_height),0.1f,1000.0f);
		//gluPerspective(60,double(_width)/double(_height),0.1,1000);

		//摄像机更新
		_camera[_cameraIndex].update();

		matrix4 matVP  =  _camera[_cameraIndex].getMVP();
		glLoadMatrixf(matVP.data());

		//glLoadMatrixf(_camera._matView.data());
		//glPushMatrix(); 
		glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
		//清成单位矩阵
		//  glLoadIdentity();//地面不动
		//glPopMatrix();
		glLoadMatrixf(matVP.data());

		glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_SIZE://窗口大小变化
			{
				if(::IsWindow(hWnd))
				{
					//获取窗口宽高
					RECT rt;
					GetClientRect(_hWnd,&rt);
					int w = rt.right - rt.left;
					int h = rt.bottom - rt.top;
					glViewport(0,0,w,h);//指定视口
					//把屏幕坐标转化成世界坐标
					_camera[_cameraIndex].setView(w,h);
				}
			}
			break;
		case WM_LBUTTONDOWN:
			{
				_bDownFlag = true;
				_mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y
			}
			break;
		case WM_LBUTTONUP:
			{
				_bDownFlag = false;
			}
			break;
		case WM_MOUSEWHEEL:
			{	
			}
		case WM_RBUTTONDOWN:
			{
              _cameraIndex  +=  1;
			  _cameraIndex  %=  3;
			}
			break;
		case WM_MOUSEMOVE:
			{
				if(_bDownFlag)
				{
					int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
					float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
					_mouseDown = mouseCur;
					_camera[_cameraIndex].rotateY(xOffset * 0.5f);
				}
			}
			break;

			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
					_rolePos.x  -=  1;
					break;
				case VK_RIGHT:
					_rolePos.x  +=  1;
					break;
				case VK_UP:
					_rolePos.z  -=  1;
					break;
				case VK_DOWN:
					_rolePos.z  +=  1;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
//Camera.h
#pragma once

#include "CELLMath.hpp"
using namespace CELL;
class Camera
{
public:
    float3 _eye;//中心点
	float3  _lookat;

	float3  _up;//定义了摄像机的y轴
	float3  _right;//定义了摄像机的x轴
	//不用定义z轴,x,y叉积是z(_eye和 _lookat形成的刚好是z轴)
	float   _speed;
	matrix4 _matView;
	matrix4 _matProj;//投影
	float2  _viewSize;
	Camera(void)
	{
       _eye    =  float3(0,0,10);
	   _lookat =  float3(0,0,0);
	   _up     =  float3(0,1,0);
	   _right  =  float3(1,0,0);
	   _speed  =  0.2f;
	}

	void  moveLeft()
	{
		_eye     -=  normalize(_right)* _speed ;//normalize(_right)将_right单位化
	    _lookat  -=  normalize(_right)* _speed ;
	}
	void  moveRight()
	{
		_eye    +=  normalize(_right)* _speed ;
	    _lookat +=  normalize(_right)* _speed ;
	}
	void  moveFront()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     += dir * _speed;
		_lookat  += dir * _speed;
	}
	void  moveBack()
	{
		float3 dir  =  normalize(_lookat - _eye);//z轴方向
		_eye     -= dir * _speed;
        _lookat  -= dir * _speed;
	}

	void setView(int x,int y)
	{
		_viewSize.x = x;
		_viewSize.y = y;
	}

	matrix4 getMVP()
	{
		return _matProj * _matView;//观察矩阵*投影矩阵
	}
	void  update()
	{
		_matView  =  lookAt(_eye,_lookat,_up);//解除对gluLookAt的依赖 
		// gluLookAt(_eye.x,_eye.y,_eye.z,_lookat.x,_lookat.y,_lookat.z,_up.x,_up.y,_up.z);
	}
	void perspective(float fovy, float aspect, float zNear, float zFar)
	{
		_matProj = CELL::perspective(fovy,aspect,zNear,zFar);//角度 宽高比 
	}
    void rotateY(float angle)
	{
       float3 dir  = normalize(_lookat -_eye);
	   float  len  = length(_lookat - _eye);
	   float3 dir1 = CELL::rotateY(dir,angle);//眼镜现在看的方向
	       _lookat = _eye  + dir1 * len;
	       _right  = normalize(cross(dir1 , _up));
	}
	virtual ~Camera(void)
	{
	}
};
  • 运行:













2月22日

  • 摄像机路径动画-曲线飞行的摄像机2
//lesson206.cpp
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"

#include "Camera.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int

	GLuint _texGround;

	Camera _camera;
	int2 _mouseDown;
	bool _bDownFlag;//鼠标按下的标志

    tspline<float> _spline;
    float _time;
public:
	SamplerTexture() 
	{
		_bDownFlag  =  false;
		
        _time  =  0;
		_camera._eye    =  float3(0,10,10);
		_camera._lookat =  float3(0,0,0);

		_spline.addPoint(float3(0,5,0));
		_spline.addPoint(float3(10,5,10));
		_spline.addPoint(float3(30,5,10));
		_spline.addPoint(float3(30,5,60));
		_spline.addPoint(float3(100,5,60));
		_spline.addPoint(float3(100,5,65));
        _spline.addPoint(float3(80,5,-80));
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)

		float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

			//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};


		//glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		
		glMatrixMode(GL_MODELVIEW);//矩阵模式要操作投影矩阵
		
		_camera.perspective(60,float(_width)/float(_height),0.1f,1000.0f);

		if (_time >= 1.0f)
		{
			_time = 0;
		}
        float3 pos = _spline.interpolate(_time);
        _time += 0.0001f;

		float3 of       = _camera._lookat - _camera._eye;
        _camera._eye    = pos;
		_camera._lookat = _camera._eye +of;

		//摄像机更新
		_camera.update();

		matrix4 matVP  =  _camera.getMVP();
		glLoadMatrixf(matVP.data());


		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
		glLoadMatrixf(matVP.data());

		glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_SIZE://窗口大小变化
			{
				if(::IsWindow(hWnd))
				{
					//获取窗口宽高
					RECT rt;
					GetClientRect(_hWnd,&rt);
					int w = rt.right - rt.left;
					int h = rt.bottom - rt.top;
					glViewport(0,0,w,h);//指定视口
					//把屏幕坐标转化成世界坐标
					_camera.setView(w,h);
				}
			}
			break;
		case WM_LBUTTONDOWN:
			{
				_bDownFlag = true;
				_mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y
			}
			break;
		case WM_LBUTTONUP:
			{
				_bDownFlag = false;
			}
			break;
		case WM_MOUSEWHEEL:
			{	
			}
		case WM_RBUTTONDOWN:
			{
			}
			break;
		case WM_MOUSEMOVE:
			{
				if(_bDownFlag)
				{
					int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
					float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
					_mouseDown = mouseCur;
					_camera.rotateY(xOffset * 0.5f);
				}
			}
			break;

			//响应键盘
		case WM_KEYDOWN:
			{
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













2月23日

  • 多视口渲染-多摄像机渲染(绘制多个OpenGL窗口)
//把整个窗口的客户区映射成OpenGL的视口,让绘制的内容在整个窗口里显示
  glViewport(0,0,_width,_height);//OpenGL视口
//lesson206.cpp
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"

#include "Camera.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int

	GLuint _texGround;

	Camera _camera;
	Camera _camera1;
	int2 _mouseDown;
	bool _bDownFlag;//鼠标按下的标志

    tspline<float> _spline;
    float _time;
public:
	SamplerTexture() 
	{
		_bDownFlag  =  false;
		
        _time  =  0;
		_camera._eye    =  float3(0,10,10);
		_camera._lookat =  float3(0,0,0);

		_camera1._eye    =  float3(0,0,10);
		_camera1._lookat =  float3(0,0,0);

		_spline.addPoint(float3(0,5,0));
		_spline.addPoint(float3(10,5,10));
		_spline.addPoint(float3(30,5,10));
		_spline.addPoint(float3(30,5,60));
		_spline.addPoint(float3(100,5,60));
		_spline.addPoint(float3(100,5,65));
        _spline.addPoint(float3(80,5,-80));
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)

		float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

			//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glViewport(0,0,_width/2,_height/2);//OpenGL视口;(0,0)在左下角

		glMatrixMode(GL_MODELVIEW);//矩阵模式要操作投影矩阵
		
		_camera.perspective(60,float(_width/2)/float(_height/2),0.1f,1000.0f);

		//摄像机更新
		_camera.update();

		matrix4 matVP  =  _camera.getMVP();
		glLoadMatrixf(matVP.data());

		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理

		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
		glLoadMatrixf(matVP.data());

		glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);


		glViewport(_width/2,0,_width/2,_height/2);//OpenGL视口;(0,0)在左下角

		glMatrixMode(GL_MODELVIEW);//矩阵模式要操作投影矩阵

		_camera1.perspective(60,float(_width/2)/float(_height/2),0.1f,1000.0f);

		//摄像机更新
		_camera1.update();

	    matrix4 mvp1  =  _camera1.getMVP();
		glLoadMatrixf(mvp1.data());

		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理

		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
		glLoadMatrixf(mvp1.data());

		glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_SIZE://窗口大小变化
			{
				if(::IsWindow(hWnd))
				{
					//获取窗口宽高
					RECT rt;
					GetClientRect(_hWnd,&rt);
					int w = rt.right - rt.left;
					int h = rt.bottom - rt.top;
					glViewport(0,0,w,h);//指定视口
					//把屏幕坐标转化成世界坐标
					_camera.setView(w,h);
				}
			}
			break;
		case WM_LBUTTONDOWN:
			{
				_bDownFlag = true;
				_mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y
			}
			break;
		case WM_LBUTTONUP:
			{
				_bDownFlag = false;
			}
			break;
		case WM_MOUSEWHEEL:
			{	
			}
		case WM_RBUTTONDOWN:
			{
			}
			break;
		case WM_MOUSEMOVE:
			{
				if(_bDownFlag)
				{
					int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
					float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
					_mouseDown = mouseCur;
					_camera.rotateY(xOffset * 0.5f);
				}
			}
			break;

			//响应键盘
		case WM_KEYDOWN:
			{
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













  • 场景-节点设计-优化绘制多个实体
场景管理里的节点:
  通过一个实际的业务需求来展现节点作用:
   将整个旋转 缩放 平移操作封装起来,形成一个节点,在场景绘制时候以节点为单位,一个节点就对应一个绘制操作

2月24日

//lesson206.cpp
//摄像机围绕物体旋转
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};
//专门提供绘制,负责提供数据
class Renderable  
{
public:

	void render(GLuint tex)
	{
		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

		};
		glBindTexture(GL_TEXTURE_2D,tex);//使用纹理

		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

		glDrawArrays(GL_QUADS,0, 24);

		glPopMatrix();
	}
};
//具体绘制到什么内容,node决定
class Node
{
public:
	float3 _trans;
	float3 _scale;//缩放
	float3 _rot;//旋转

	void render(GLuint tex,matrix4& vp)
	{
		matrix4 trans(1);
		trans.translate(_trans);
		matrix4 mvp =vp *trans;
		glLoadMatrixf(mvp.data());

		_renderable->render(tex);
	}
	Renderable* _renderable;
	
};

typedef std::vector<Node> ArrayNode;

class SamplerTexture:public OpenGLWindow
{
public:

	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int

	GLuint _texGround;

	Camera3rd _camera;
	int2 _mouseDown;
	bool _bDownFlag;//鼠标按下的标志

	float3 _rolePos;

	ArrayNode _nodes;  
	Renderable _renderable;
public:
	SamplerTexture() 
	{
		_bDownFlag  =  false;
		_rolePos    =  float3(0,0,0);

		for(int i=0;i<100;++i)
		{
			Node node;
			node._trans.x  =  rand()%200 - 100;
			node._trans.y  =  rand()%10  + 10;
			node._trans.z  =  rand()%200 - 100;
            node._renderable = &_renderable;
			_nodes.push_back(node);

		}
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		_texture    =   createTextureFromImage("1.jpg");
		_texGround = createTextureFromImage("2.jpg");
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)


		float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

			//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};

		glMatrixMode(GL_MODELVIEW);//矩阵模式要操作投影矩阵

		_camera.perspective(60,float(_width)/float(_height),0.1f,1000.0f);

		_camera.updateLookat(_rolePos);
		//摄像机更新
		_camera.update();

		matrix4 matVP  =  _camera.getMVP();
		glLoadMatrixf(matVP.data());

		glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);
		glBindTexture(GL_TEXTURE_2D,_texture);//使用纹理

		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

		glDrawArrays(GL_QUADS, 0,24);
		glLoadMatrixf(matVP.data());

		glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

		glBindTexture(GL_TEXTURE_2D,_texture);
        for (size_t i=0;i<_nodes.size(); ++ i)
        {
			_nodes[i].render(_texture,matVP);
        }
	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_LBUTTONDOWN:
			{
				_bDownFlag = true;
				_mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y
			}
			break;
		case WM_LBUTTONUP:
			{
				_bDownFlag = false;
			}
			break;
		case WM_MOUSEWHEEL:
			{
				int delta = (short)HIWORD(wParam);//鼠标滚动过的距离(120的整数倍,正的即正向滚动)
				if (delta > 0)
				{
					_camera.setRadius(_camera.getRadius() * 1.2f);
				}
				else
				{
					_camera.setRadius(_camera.getRadius() * 0.8f);
				}
			}
		case WM_MOUSEMOVE:
			{
				if(_bDownFlag)
				{
					int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
					float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
					_mouseDown = mouseCur;
					_camera.rotateY(xOffset * 0.5f);
				}
			}
			break;

			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
					_rolePos.x  -=  1;
					break;
				case VK_RIGHT:
					_rolePos.x  +=  1;
					break;
				case VK_UP:
					_rolePos.z  -=  1;
					break;
				case VK_DOWN:
					_rolePos.z  +=  1;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













2月25日

  • 场景-节点裁剪-大规模绘制的利器
//lesson206.cpp
//摄像机围绕物体旋转
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};
//专门提供绘制,负责提供数据
class Renderable  
{
public:

	void render(GLuint tex)
	{
		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

		};
		glBindTexture(GL_TEXTURE_2D,tex);//使用纹理

		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

		glDrawArrays(GL_QUADS,0, 24);

		glPopMatrix();
	}
};
//具体绘制到什么内容,node决定
class Node
{
public:
	float3 _trans;
	float3 _scale;//缩放
	float3 _rot;//旋转

	void render(GLuint tex,matrix4& vp)
	{
		matrix4 trans(1);
		trans.translate(_trans);
		matrix4 mvp =vp *trans;
		glLoadMatrixf(mvp.data());

		_renderable->render(tex);
	}
	Renderable* _renderable;
	
};

typedef std::vector<Node> ArrayNode;

class SamplerTexture:public OpenGLWindow
{
public:

	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int

	GLuint _texGround;

	Camera3rd _camera;
	int2 _mouseDown;
	bool _bDownFlag;//鼠标按下的标志

	float3 _rolePos;

	ArrayNode _nodes;  
	Renderable _renderable;
    Frustum  _frust;
public:
	SamplerTexture() 
	{
		_bDownFlag  =  false;
		_rolePos    =  float3(0,0,0);

		for(int i=0;i<100;++i)
		{
			Node node;
			node._trans.x  =  rand()%200 - 100;
			node._trans.y  =  rand()%10  + 10;
			node._trans.z  =  rand()%200 - 100;
            node._renderable = &_renderable;
			_nodes.push_back(node);

		}
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		_texture    =   createTextureFromImage("1.jpg");
		_texGround = createTextureFromImage("2.jpg");
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)


		float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

			//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};

		glMatrixMode(GL_MODELVIEW);//矩阵模式要操作投影矩阵

		_camera.perspective(60,float(_width)/float(_height),0.1f,1000.0f);

		_camera.updateLookat(_rolePos);
		//摄像机更新
		_camera.update();

		matrix4 matVP  =  _camera.getMVP();
		glLoadMatrixf(matVP.data());
        matrix4 temp   =   matVP.transpose();//转置
       
		_frust.loadFrustum(temp);//里以行为主

		glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);
		glBindTexture(GL_TEXTURE_2D,_texture);//使用纹理

		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

		glDrawArrays(GL_QUADS, 0,24);
		glLoadMatrixf(matVP.data());

		glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

		glBindTexture(GL_TEXTURE_2D,_texture);

		int iCount =  0;//记录画了多少个
        for (size_t i = 0;i<_nodes.size(); ++ i)
        {
			if (_frust.sphereInFrustum(_nodes[i]._trans,1.5f))
			{
				++iCount;
				_nodes[i].render(_texture,matVP);
			}
			
        }
		char szBuf[128];
		sprintf(szBuf,"%d",iCount);
		SetWindowTextA(_hWnd,szBuf);//设置标题栏文字


	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_LBUTTONDOWN:
			{
				_bDownFlag = true;
				_mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y
			}
			break;
		case WM_LBUTTONUP:
			{
				_bDownFlag = false;
			}
			break;
		case WM_MOUSEWHEEL:
			{
				int delta = (short)HIWORD(wParam);//鼠标滚动过的距离(120的整数倍,正的即正向滚动)
				if (delta > 0)
				{
					_camera.setRadius(_camera.getRadius() * 1.2f);
				}
				else
				{
					_camera.setRadius(_camera.getRadius() * 0.8f);
				}
			}
		case WM_MOUSEMOVE:
			{
				if(_bDownFlag)
				{
					int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
					float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
					_mouseDown = mouseCur;
					_camera.rotateY(xOffset * 0.5f);
				}
			}
			break;

			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
					_rolePos.x  -=  1;
					break;
				case VK_RIGHT:
					_rolePos.x  +=  1;
					break;
				case VK_UP:
					_rolePos.z  -=  1;
					break;
				case VK_DOWN:
					_rolePos.z  +=  1;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













2月27日

  • 地形的介绍-地形网络的生成(三角形带绘制地形)
#pragma once


struct  TerrainVert
{
    float   x,y,z;
};


class Terrain
{
public:
    typedef std::vector<TerrainVert>    ArrayVertex;
public:
    ArrayVertex _vertex;
    int         _drawSize;

public:

    Terrain(void)
    {
    }

    ~Terrain(void)
    {
    }

    void    setup(float w,float h)//网格的宽高
    {
		//屏幕中心点为(0,0)
        float   step    =   1;
        float   startX  =   -w * 0.5f;
        float   startZ  =   -h * 0.5f;

        float   halfW   =   w * 0.5f;
        float   halfH   =   h * 0.5f;

        _drawSize       =   (w/step) * 2;
        
        for (float z = startZ ; z < halfW ; z += step)
        {
            for (float x = startX ; x < halfH ; x += step)
            {
                TerrainVert vert0   =   {x,         0,  z       }; //左下角点    
                TerrainVert vert1   =   {x,         0,  z + step}; //左下角向上一点 

                _vertex.push_back(vert0);
                _vertex.push_back(vert1);
            }
        }
    }

    void    render()
    {
        glEnableClientState(GL_VERTEX_ARRAY);//禁掉纹理坐标
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(TerrainVert),     &_vertex[0].x);
      
        for (size_t i = 0 ;i < _vertex.size() ; i += _drawSize)
        {
            glDrawArrays(GL_TRIANGLE_STRIP,i,_drawSize);
        }
    }
};
//lesson206.cpp
//新增功能:投影转化
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
#include "Terrain.hpp"
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture[6];//纹理句柄;数字,无符号int

	GLuint _texGround;

	Camera3rd _camera;
	int2 _mouseDown;
	bool _bDownFlag;//鼠标按下的标志

	float3 _rolePos;
	float3 _moveTo;
	Terrain _terrain;
public:
	SamplerTexture() 
	{
		_bDownFlag  =  false;
		_rolePos    =  float3(0,0,0);
		_moveTo     =  _rolePos;
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{
		char* fileName[6]=
		{
			"image/1.jpg",
			"image/2.jpg",
			"image/3.jpg",
			"image/4.jpg",
			"image/5.jpg",
			"image/6.jpg",
		};
		for(int i=0;i<6;++i)
		{
			_texture[i] = createTextureFromImage(fileName[i]);
		}

		_texGround = createTextureFromImage("2.jpg");
        _terrain.setup(100,100);

		glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
	}
	//释放资源
	virtual void onShutdownGL()
	{
		glDeleteTextures(6,_texture);
		int err = glGetError();
	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)

		float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

			//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};


		//glMatrixMode(GL_MODELVIEW);//指定矩阵模式:模型矩阵
		glBindTexture(GL_TEXTURE_2D,_texture[0]);//使用纹理
#if 0

		glEnable(GL_DEPTH_TEST);//深度测试
		glInterleavedArrays(GL_T2F_V3F, 0,cubeVertices);//GL_C4UB_V3F和cubeVertices要严格对应

#else 
		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);
#endif
		//指定模型矩阵-产生投影矩阵-产生观察矩阵-将观察矩阵*投影矩阵当成模型矩阵
		//glLoadIdentity();

		glMatrixMode(GL_MODELVIEW);//矩阵模式要操作投影矩阵
		//glLoadIdentity();//将投影矩阵清空成单位矩阵

		_camera.perspective(60,float(_width)/float(_height),0.1f,1000.0f);
		//gluPerspective(60,double(_width)/double(_height),0.1,1000);

		float3 dir = normalize(_moveTo - _rolePos);//得到移动的方向

		if (length(_moveTo - _rolePos) < 1)
		{
			_rolePos = _moveTo;
		}
		else 
		{
			_rolePos += dir * 1.0f/60.0f;
		}
		_camera.updateLookat(_rolePos);
		//摄像机更新
		_camera.update();

		matrix4 matVP  =  _camera.getMVP();
		glLoadMatrixf(matVP.data());

		//glLoadMatrixf(_camera._matView.data());
		//glPushMatrix(); 
		glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

		for(int i = 0;i < 6;++i)
		{
			glBindTexture(GL_TEXTURE_2D,_texture[i]);
			glDrawArrays(GL_QUADS, i*4, 4);
		}
		//清成单位矩阵
		//  glLoadIdentity();//地面不动
		//glPopMatrix();
		glLoadMatrixf(matVP.data());

		//glBindTexture(GL_TEXTURE_2D,_texGround);
		//glDrawArrays(GL_QUADS,24,4);

		_terrain.render();
	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_SIZE://窗口大小变化
			{
				if(::IsWindow(hWnd))
				{
					//获取窗口宽高
					RECT rt;
					GetClientRect(_hWnd,&rt);
					int w = rt.right - rt.left;
					int h = rt.bottom - rt.top;
					glViewport(0,0,w,h);//指定视口
					//把屏幕坐标转化成世界坐标
					_camera.setView(w,h);
				}
			}
			break;
		case WM_LBUTTONDOWN:
			{
				_bDownFlag = true;
				_mouseDown = int2(LOWORD(lParam),HIWORD(lParam));//低字节保存的x,高字节保存的y

				CELL::Ray ray = _camera.createRayFromScreen(_mouseDown.x,_mouseDown.y);
				float3   orth = ray.getOrigin();
				float    tm   = (orth.y - (-1))/ray.getDirection().y;//多长时间到达地面
				float3   c    = ray.getOrigin() + abs(tm) * ray.getDirection();
				_moveTo = c;
			}
			break;
		case WM_LBUTTONUP:
			{
				_bDownFlag = false;
			}
			break;
		case WM_MOUSEWHEEL:
			{
				int delta = (short)HIWORD(wParam);//鼠标滚动过的距离(120的整数倍,正的即正向滚动)
				if (delta > 0)
				{
					_camera.setRadius(_camera.getRadius() * 1.2f);
				}
				else
				{
					_camera.setRadius(_camera.getRadius() * 0.8f);
				}
			}
		case WM_MOUSEMOVE:
			{
				if(_bDownFlag)
				{
					int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
					float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
					_mouseDown = mouseCur;
					_camera.rotateY(xOffset * 0.5f);
				}
			}
			break;

			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
					_rolePos.x  -=  1;
					break;
				case VK_RIGHT:
					_rolePos.x  +=  1;
					break;
				case VK_UP:
					_rolePos.z  -=  1;
					break;
				case VK_DOWN:
					_rolePos.z  +=  1;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}
  • 运行:













2月28日

  • 地形网络的优化-索引方式绘制
算索引:生成顶点数据,产生索引
降低显存,只存100个点
#pragma once


struct  TerrainVert
{
    float   x,y,z;
};


class Terrain
{
public:
    typedef std::vector<TerrainVert>    ArrayVertex;
    typedef std::vector<unsigned short>    ArrayIndex;
public:
    ArrayVertex _vertex;
	ArrayIndex  _index;
    int         _drawSize;

public:

    Terrain(void)
    {
    }

    ~Terrain(void)
    {
    }

    void    setup(float w,float h)//网格的宽高
    {
		//屏幕中心点为(0,0)
        float   step    =   1;
        float   startX  =   -w * 0.5f;
        float   startZ  =   -h * 0.5f;

        float   halfW   =   w * 0.5f;
        float   halfH   =   h * 0.5f;

        _drawSize       =   (w/step) * 2;
        
		/*产生顶点数据*/
        for (float z = startZ ; z <= halfW ; z += step)
        {
            for (float x = startX ; x <= halfH ; x += step)
            {
                TerrainVert vert0   =   {x,         0,  z       }; //左下角点    

                _vertex.push_back(vert0);
            }
        }
		/*计算索引数据*/
        //1行有多少个 w/step=100 w/step可能会出小数,故+0.05 向上取整
		size_t col = int(w/step + 0.5f) + 1;
		size_t row = int(h/step + 0.5f) + 1;

		for(size_t r = 0;r < row - 1;++ r)
		{
			for(size_t i = 0; i < col - 1; ++ i)
			{   
				//5 6 7 8 9
				//0 1 2 3 4
				_index.push_back((r + 0) * col + i);//0
				_index.push_back((r + 1) * col + i);//5
				_index.push_back((r + 0) * col + i + 1);//1

				_index.push_back((r + 1) * col + i);//5
				_index.push_back((r + 0) * col + i + 1);//6
				_index.push_back((r + 1) * col + i + 1);//1

			}
		}
    }

    void    render()
    {
        glEnableClientState(GL_VERTEX_ARRAY);//禁掉纹理坐标
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(TerrainVert),     &_vertex[0].x);//指定顶点数据
      
        glDrawElements(GL_TRIANGLES,_index.size(),GL_UNSIGNED_SHORT,&_index.front());
    }
};

lessonA01.cpp不变

  • 运行结果与上节相同

3月1日

  • 地形数据-高度图
//lessonA02更新数据
virtual void onInitGL()
	{
			_texture= createTextureFromImage("1.jpg");

		_texGround = createTextureFromImage("2.jpg");
		_terrain.setup(1024,1024);

		//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
	}
#pragma once


struct  TerrainVert
{
	float   x,y,z;
};

#define MAP_SIZE 1024
class Terrain
{
public:
	typedef std::vector<TerrainVert>    ArrayVertex;
	typedef std::vector<unsigned short>    ArrayIndex;
public:
	ArrayVertex _vertex;
	ArrayIndex  _index;
	int         _drawSize;

public:

	Terrain(void)
	{
	}

	~Terrain(void)
	{
	}

	bool loadHeight(const char* fileName,BYTE* pHeightMap,int w,int h)//pHeightMap:内存
	{
		FILE* pFile = fopen(fileName,"rb");
		if (pFile == NULL)
		{
			return false;
		}
		fread(pHeightMap,1,w * h,pFile);
		fclose(pFile);
		return true;
	}
	float readHeight(int x,int y,const BYTE* data)
	{
		x = x % MAP_SIZE;
		y = y % MAP_SIZE;

		return (float)data[x + (y * MAP_SIZE)];
	}
	void    setup(float w,float h)//网格的宽高
	{

		float   step    =   8;

		BYTE* data = new BYTE[MAP_SIZE * MAP_SIZE];
		loadHeight("Terrain.raw",data,MAP_SIZE,MAP_SIZE);

		/*产生顶点数据*/
		for (float z = 0 ; z <= MAP_SIZE ; z += step)
		{
			for (float x = 0 ; x <= MAP_SIZE ; x += step)
			{
				TerrainVert vert0   =   {x,readHeight(x,z,data),  z}; //左下角点    
				vert0.x -= MAP_SIZE * 0.5f;
				vert0.z -= MAP_SIZE * 0.5f;
				_vertex.push_back(vert0);
			}
		}
		delete []data;

		/*计算索引数据*/
		//1行有多少个 w/step=100 w/step可能会出小数,故+0.05 向上取整
		size_t col = int(w/step + 0.5f) + 1;
		size_t row = int(h/step + 0.5f) + 1;

		for(size_t r = 0;r < row - 1;++ r)
		{
			for(size_t i = 0; i < col - 1; ++ i)
			{   
				//5 6 7 8 9
				//0 1 2 3 4
				_index.push_back((r + 0) * col + i);//0
				_index.push_back((r + 1) * col + i);//5
				_index.push_back((r + 0) * col + i + 1);//1

				_index.push_back((r + 1) * col + i);//5
				_index.push_back((r + 0) * col + i + 1);//6
				_index.push_back((r + 1) * col + i + 1);//1

			}
		}
	}

	void    render()
	{
		glEnableClientState(GL_VERTEX_ARRAY);//禁掉纹理坐标
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,         sizeof(TerrainVert),     &_vertex[0].x);//指定顶点数据

		glDrawElements(GL_TRIANGLES,_index.size(),GL_UNSIGNED_SHORT,&_index.front());
	}
};
  • 运行:













  • 地形数据-高度颜色
#pragma once


struct  TerrainVert
{
	float   x,y,z;
	float   r,g,b,a;
};

#define MAP_SIZE 1024
class Terrain
{
public:
	typedef std::vector<TerrainVert>    ArrayVertex;
	typedef std::vector<unsigned short>    ArrayIndex;
public:
	ArrayVertex _vertex;
	ArrayIndex  _index;
	int         _drawSize;

public:

	Terrain(void)
	{
	}

	~Terrain(void)
	{
	}

	bool loadHeight(const char* fileName,BYTE* pHeightMap,int w,int h)//pHeightMap:内存
	{
		FILE* pFile = fopen(fileName,"rb");
		if (pFile == NULL)
		{
			return false;
		}
		fread(pHeightMap,1,w * h,pFile);
		fclose(pFile);
		return true;
	}
	float readHeight(int x,int y,const BYTE* data)
	{
		x = x % MAP_SIZE;
		y = y % MAP_SIZE;

		return (float)data[x + (y * MAP_SIZE)];
	}
	//根据给定的坐标来计算点的颜色
	float readColor(int x,int y,const BYTE* data)
	{
		return -0.15f + (readHeight(x,y,data)/256.0f);
	}
	void    setup(float w,float h)//网格的宽高
	{

		float   step    =   8;

		BYTE* data = new BYTE[MAP_SIZE * MAP_SIZE];
		loadHeight("Terrain.raw",data,MAP_SIZE,MAP_SIZE);

		/*产生顶点数据*/
		for (float z = 0 ; z <= MAP_SIZE ; z += step)
		{
			for (float x = 0 ; x <= MAP_SIZE ; x += step)
			{
				TerrainVert vert0   =   {x,readHeight(x,z,data),  z,0,0,0,1}; //左下角点    
				vert0.x -= MAP_SIZE * 0.5f;
				vert0.z -= MAP_SIZE * 0.5f;
				vert0.r = 0;
				vert0.g = readColor(x,z,data);
				vert0.b = 0;
				vert0.a = 1;                           
				_vertex.push_back(vert0);
			}
		}
		delete []data;

		/*计算索引数据*/
		//1行有多少个 w/step=100 w/step可能会出小数,故+0.05 向上取整
		size_t col = int(w/step + 0.5f) + 1;
		size_t row = int(h/step + 0.5f) + 1;

		for(size_t r = 0;r < row - 1;++ r)
		{
			for(size_t i = 0; i < col - 1; ++ i)
			{   
				//5 6 7 8 9
				//0 1 2 3 4
				_index.push_back((r + 0) * col + i);//0
				_index.push_back((r + 1) * col + i);//5
				_index.push_back((r + 0) * col + i + 1);//1

				_index.push_back((r + 1) * col + i);//5
				_index.push_back((r + 0) * col + i + 1);//6
				_index.push_back((r + 1) * col + i + 1);//1

			}
		}
	}

	void    render()
	{
		glEnableClientState(GL_VERTEX_ARRAY);//禁掉纹理坐标
		glEnableClientState(GL_COLOR_ARRAY);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(TerrainVert),&_vertex[0].x);//指定顶点数据
		glColorPointer(4,GL_FLOAT,sizeof(TerrainVert),&_vertex[0].r);

		glDrawElements(GL_TRIANGLES,_index.size(),GL_UNSIGNED_SHORT,&_index.front());
	}
};
  • 运行:













3月2日

  • 地形数据-法线
#pragma once


struct  TerrainVert
{
	float   x,y,z;
	float   nx,ny,nz;//法线
	float   r,g,b,a;
};

#define MAP_SIZE 1024
class Terrain
{
public:
	typedef std::vector<TerrainVert>    ArrayVertex;
	typedef std::vector<unsigned short>    ArrayIndex;
public:
	ArrayVertex _vertex;
	ArrayIndex  _index;
	int         _drawSize;

public:

	Terrain(void)
	{
	}

	~Terrain(void)
	{
	}

	bool loadHeight(const char* fileName,BYTE* pHeightMap,int w,int h)//pHeightMap:内存
	{
		FILE* pFile = fopen(fileName,"rb");
		if (pFile == NULL)
		{
			return false;
		}
		fread(pHeightMap,1,w * h,pFile);
		fclose(pFile);
		return true;
	}
	float readHeight(int x,int y,const BYTE* data)
	{
		x = x % MAP_SIZE;
		y = y % MAP_SIZE;

		return (float)data[x + (y * MAP_SIZE)];
	}
	//根据给定的坐标来计算点的颜色
	float readColor(int x,int y,const BYTE* data)
	{
		return -0.15f + (readHeight(x,y,data)/256.0f);
	}

	float3 computeNomal(TerrainVert& v1,TerrainVert& v2,TerrainVert& v3)
	{
		float3 f1(v2.x - v1.x,v2.y - v1.y,v2.z - v1.z);
        float3 f2(v3.x - v1.x,v3.y - v1.y,v3.z - v1.z);
		return normalize(cross(f1,f2));
	}
	void    setup(float w,float h)//网格的宽高
	{

		float   step    =   8;

		BYTE* data = new BYTE[MAP_SIZE * MAP_SIZE];
		loadHeight("Terrain.raw",data,MAP_SIZE,MAP_SIZE);

		/*产生顶点数据*/

		for (float z = 0 ; z <= MAP_SIZE ; z += step)
		{
			for (float x = 0 ; x <= MAP_SIZE ; x += step)
			{
				TerrainVert vert0   =   {x,readHeight(x,z,data),  z,0,0,0,1}; //左下角点    
				vert0.x -= MAP_SIZE * 0.5f;
				vert0.z -= MAP_SIZE * 0.5f;
				vert0.r = 0;
				vert0.g = readColor(x,z,data);
				vert0.b = 0;
				vert0.a = 1;                           
				_vertex.push_back(vert0);
			}
		}
		delete []data;

		/*计算索引数据*/

		//1行有多少个 w/step=100 w/step可能会出小数,故+0.05 向上取整
		size_t col = int(w/step + 0.5f) + 1;
		size_t row = int(h/step + 0.5f) + 1;

		for(size_t r = 0;r < row - 1;++ r)
		{
			for(size_t i = 0; i < col - 1; ++ i)
			{   
				//5 6 7 8 9
				//0 1 2 3 4
				_index.push_back((r + 0) * col + i);//0
				_index.push_back((r + 1) * col + i);//5
				_index.push_back((r + 0) * col + i + 1);//1

				_index.push_back((r + 1) * col + i);//5
				_index.push_back((r + 0) * col + i + 1);//6
				_index.push_back((r + 1) * col + i + 1);//1

			}
		}
        /*计算法线*/
		for(size_t i = 0;i < _index.size();i += 3)
		{
			TerrainVert&  v0 = _vertex[_index[i+0]];
            TerrainVert&  v1 = _vertex[_index[i+1]];
			TerrainVert&  v2 = _vertex[_index[i+2]];
			float3        nor= computeNomal(v0,v1,v2); //计算法线
         //采用面法线 (没有点法线效果好)
			v0.nx = nor.x;
            v0.ny = nor.y;
			v0.nz = nor.z;

			v1.nx = nor.x;
			v1.ny = nor.y;
			v1.nz = nor.z;

			v2.nx = nor.x;
			v2.ny = nor.y;
			v2.nz = nor.z;
		}

	}

	void    render()
	{
		glEnableClientState(GL_VERTEX_ARRAY);//禁掉纹理坐标
		glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
		glDisableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(TerrainVert),&_vertex[0].x);//指定顶点数据
		glNormalPointer(GL_FLOAT,sizeof(TerrainVert),&_vertex[0].nx);
		glColorPointer(4,GL_FLOAT,sizeof(TerrainVert),&_vertex[0].r);

		glDrawElements(GL_TRIANGLES,_index.size(),GL_UNSIGNED_SHORT,&_index.front());
	    glDisableClientState(GL_COLOR_ARRAY);
		glDisableClientState(GL_NORMAL_ARRAY);
	}
};

更新lessonA04 的onInitGL()函数

virtual void onInitGL()
	{
			_texture= createTextureFromImage("1.jpg");

		_texGround = createTextureFromImage("2.jpg");
		_terrain.setup(1024,1024);
		glEnable(GL_LIGHTING);
		glEnable(GL_LIGHT0);

		GLfloat diffuse_light0[] = {1.0f,1.0f,1.0f,1.0f };//默认光颜色
		GLfloat position_light0[] = {0, 10, 0, 0.0f};//光的位置
		glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse_light0);
		glLightfv(GL_LIGHT0,GL_POSITION,position_light0);

		//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
	}
  • 运行:













3月3日

  • 地形数据-纹理
#pragma once


struct  TerrainVert
{
	float   x,y,z;
	float   nx,ny,nz;//法线
	float   u,v;
	float   r,g,b,a;
};

#define MAP_SIZE 1024
class Terrain
{
public:
	typedef std::vector<TerrainVert>    ArrayVertex;
	typedef std::vector<unsigned short>    ArrayIndex;
public:
	ArrayVertex _vertex;
	ArrayIndex  _index;
	int         _drawSize;

public:

	Terrain(void)
	{
	}

	~Terrain(void)
	{
	}

	bool loadHeight(const char* fileName,BYTE* pHeightMap,int w,int h)//pHeightMap:内存
	{
		FILE* pFile = fopen(fileName,"rb");
		if (pFile == NULL)
		{
			return false;
		}
		fread(pHeightMap,1,w * h,pFile);
		fclose(pFile);
		return true;
	}
	float readHeight(int x,int y,const BYTE* data)
	{
		x = x % MAP_SIZE;
		y = y % MAP_SIZE;

		return (float)data[x + (y * MAP_SIZE)];
	}
	//根据给定的坐标来计算点的颜色
	float readColor(int x,int y,const BYTE* data)
	{
		return -0.15f + (readHeight(x,y,data)/256.0f);
	}

	float3 computeNomal(TerrainVert& v1,TerrainVert& v2,TerrainVert& v3)
	{
		float3 f1(v2.x - v1.x,v2.y - v1.y,v2.z - v1.z);
        float3 f2(v3.x - v1.x,v3.y - v1.y,v3.z - v1.z);
		return normalize(cross(f1,f2));
	}
	void    setup(float w,float h)//网格的宽高
	{

		float   step    =   8;

		BYTE* data = new BYTE[MAP_SIZE * MAP_SIZE];
		loadHeight("Terrain.raw",data,MAP_SIZE,MAP_SIZE);

		/*产生顶点数据*/

		for (float z = 0 ; z <= MAP_SIZE ; z += step)
		{
			for (float x = 0 ; x <= MAP_SIZE ; x += step)
			{
				TerrainVert vert0   =   {x,readHeight(x,z,data),  z,0,0,0,1}; //左下角点    
				vert0.x -= MAP_SIZE * 0.5f;
				vert0.z -= MAP_SIZE * 0.5f;
				vert0.r = 0;
				vert0.g = readColor(x,z,data);
				vert0.b = 0;
				vert0.a = 1;          
				vert0.u = float(x)/MAP_SIZE * 10;//x最大值MAP_SIZE
				vert0.v = float(z)/MAP_SIZE * 10;
				_vertex.push_back(vert0);
			}
		}
		delete []data;

		/*计算索引数据*/

		//1行有多少个 w/step=100 w/step可能会出小数,故+0.05 向上取整
		size_t col = int(w/step + 0.5f) + 1;
		size_t row = int(h/step + 0.5f) + 1;

		for(size_t r = 0;r < row - 1;++ r)
		{
			for(size_t i = 0; i < col - 1; ++ i)
			{   
				//5 6 7 8 9
				//0 1 2 3 4
				_index.push_back((r + 0) * col + i);//0
				_index.push_back((r + 1) * col + i);//5
				_index.push_back((r + 0) * col + i + 1);//1

				_index.push_back((r + 1) * col + i);//5
				_index.push_back((r + 0) * col + i + 1);//6
				_index.push_back((r + 1) * col + i + 1);//1

			}
		}
        /*计算法线*/
		for(size_t i = 0;i < _index.size();i += 3)
		{
			TerrainVert&  v0 = _vertex[_index[i+0]];
            TerrainVert&  v1 = _vertex[_index[i+1]];
			TerrainVert&  v2 = _vertex[_index[i+2]];
			float3        nor= computeNomal(v0,v1,v2); //计算法线
         //采用面法线 (没有点法线效果好)
			v0.nx = nor.x;
            v0.ny = nor.y;
			v0.nz = nor.z;

			v1.nx = nor.x;
			v1.ny = nor.y;
			v1.nz = nor.z;

			v2.nx = nor.x;
			v2.ny = nor.y;
			v2.nz = nor.z;
		}

	}

	void    render()
	{
		glEnableClientState(GL_VERTEX_ARRAY);//禁掉纹理坐标
		glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);//启用顶点状态
		glVertexPointer(3,GL_FLOAT,sizeof(TerrainVert),&_vertex[0].x);//指定顶点数据
		glNormalPointer(GL_FLOAT,sizeof(TerrainVert),&_vertex[0].nx);
		glColorPointer(4,GL_FLOAT,sizeof(TerrainVert),&_vertex[0].r);
        glTexCoordPointer(2,GL_FLOAT,sizeof(TerrainVert),&_vertex[0].u);
		glDrawElements(GL_TRIANGLES,_index.size(),GL_UNSIGNED_SHORT,&_index.front());
	    
		glDisableClientState(GL_COLOR_ARRAY);
		glDisableClientState(GL_NORMAL_ARRAY);
	}
};

lessonA05.cpp更新onInitGL()

virtual void onInitGL()
	{
		_texture= createTextureFromImage("1.jpg");
		_texGround = createTextureFromImage("2.jpg");
		_terrainTex= createTextureFromImage("Terrain.bmp");
		_terrain.setup(1024,1024);
		glEnable(GL_LIGHTING);
		glEnable(GL_LIGHT0);

		GLfloat diffuse_light0[] = {1.0f,1.0f,1.0f,1.0f };//默认光颜色
		GLfloat position_light0[] = {0, 10, 0, 0.0f};//光的位置
		glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse_light0);
		glLightfv(GL_LIGHT0,GL_POSITION,position_light0);

		//glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
	}
  • 运行:













3月4日

  • 地形数据-雾
//lesson206.cpp
//新增功能:投影转化
#include <windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
#include "Terrain.hpp"
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};

class   SamplerTerrain :public OpenGLWindow
{
    GLuint  _texture;

    GLuint  _texGround;
    GLuint  _terrainTex;

    Camera3rd  _camera;
    int2    _mouseDown;
    bool    _bDownFlag;


    float3  _rolePos;
    float3  _moveTo;
    Terrain _terrain;
public:
    SamplerTerrain() 
    {
        _bDownFlag  =   false;
        _rolePos    =   float3(0,0,0);
        _moveTo     =   _rolePos;
    }         
    /**
    *   使用FreeImage加载图片
    */
    unsigned        createTextureFromImage(const char* fileName)
    {
        //1 获取图片格式
        FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
        if (fifmt == FIF_UNKNOWN)
        {
            return  0;
        }
        //2 加载图片
        FIBITMAP    *dib = FreeImage_Load(fifmt, fileName,0);
     
        FREE_IMAGE_COLOR_TYPE type    =   FreeImage_GetColorType(dib);
      
        //! 获取数据指针
        FIBITMAP*   temp    =   dib;
        dib =   FreeImage_ConvertTo32Bits(dib);
                FreeImage_Unload(temp);

        BYTE*   pixels =   (BYTE*)FreeImage_GetBits(dib);
        int     width   =   FreeImage_GetWidth(dib);
        int     height  =   FreeImage_GetHeight(dib);

        for (int i = 0 ;i < width * height * 4 ; i+=4 )
        {
            BYTE temp       =   pixels[i];
            pixels[i]       =   pixels[i + 2];
            pixels[i + 2]   =   temp;
        }

        unsigned    res =   createTexture(width,height,pixels);
        FreeImage_Unload(dib);
        return      res;
    }

    unsigned        createTexture(int w,int h,const void* data)
    {
        unsigned    texId;
        glGenTextures(1,&texId);
        glBindTexture(GL_TEXTURE_2D,texId);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);

        return  texId;
    }

    virtual void    onInitGL()
    {
        _texture    =   createTextureFromImage("2.jpg");
        _texGround  =   createTextureFromImage("1.jpg");
        _terrainTex =   createTextureFromImage("Terrain.bmp");
        _terrain.setup(1024,1024);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);

        GLfloat diffuse_light0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
        GLfloat position_light0[] = { 0, 10, 0, 0.0f };
        glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse_light0 );
        glLightfv( GL_LIGHT0, GL_POSITION, position_light0 );

        float fogColor[4] = {0.8f, 0.8f, 0.8f, 1.0f};

        glEnable(GL_FOG);   
        glFogi(GL_FOG_MODE, GL_LINEAR);	
        glFogfv(GL_FOG_COLOR, fogColor);
        glFogf(GL_FOG_START, 0.0);
        glFogf(GL_FOG_END, 50.0);

        glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);

    }
    virtual void    render()
    {
#define M_PI (3.14159265358979323846)
       

        float   size    =   100;

        Vertex cubeVertices[] =
        {
            {  -1.0f,-1.0f, 1.0f    ,0.3f,  0.3f },
            {  1.0f,-1.0f, 1.0f     ,0.5f,  0.3f },
            {  1.0f, 1.0f, 1.0f     ,0.5f,  0.8f },
            { -1.0f, 1.0f, 1.0f     ,0.3f,  0.8f },

            {  -1.0f,-1.0f,-1.0f    ,0,  0 },
            {  -1.0f, 1.0f,-1.0f    ,1,  0 },
            {  1.0f, 1.0f,-1.0f     ,1,  1 },
            {  1.0f,-1.0f,-1.0f     ,0,  1 },

            {  -1.0f, 1.0f,-1.0f    ,0,  0 },
            {  -1.0f, 1.0f, 1.0f    ,1,  0 },
            {  1.0f, 1.0f, 1.0f     ,1,  1 },
            {  1.0f, 1.0f,-1.0f     ,0,  1 },

            {  -1.0f,-1.0f,-1.0f    ,0,  0 },
            {  1.0f,-1.0f,-1.0f     ,1,  0 },
            {  1.0f,-1.0f, 1.0f     ,1,  1 },
            {  -1.0f,-1.0f, 1.0f    ,0,  1 },

            {  1.0f,-1.0f,-1.0f ,0,  0 },
            {  1.0f, 1.0f,-1.0f ,1,  0 },
            {  1.0f, 1.0f, 1.0f ,1,  1 },
            {  1.0f,-1.0f, 1.0f ,0,  1 },

            {  -1.0f,-1.0f,-1.0f ,0,  0 },
            {  -1.0f,-1.0f, 1.0f ,1,  0 },
            {  -1.0f, 1.0f, 1.0f ,1,  1 },
            {  -1.0f, 1.0f,-1.0f ,0,  1 },

//! 地面数据

            {  -size, -1,    -size       ,0,  0 },
            {  -size, -1,    size        ,100,  0 },
            {  size,  -1,     size        ,100,  100 },
            {  size,  -1,     -size       ,0,  100 },
        };

        //! 指定以下的操作针对投影矩阵
        glMatrixMode(GL_MODELVIEW);

        _camera.perspective(60,float(_width)/float(_height),0.1f,10000.0f);
        
        float3  dir =   normalize(_moveTo - _rolePos);

        if (length(_moveTo - _rolePos) < 1)
        {
            _rolePos    =   _moveTo;
        }
        else
        {
            _rolePos    +=  dir * (10.0f/60.0f);
        }

        _camera.updateLookat(_rolePos);
        //! 摄像机更新
        _camera.update();

        matrix4 matVP  =   _camera.getMVP();
        glLoadMatrixf(matVP.data());
        
        //! 产生一个矩阵
        glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

        glBindTexture(GL_TEXTURE_2D,_texture);

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(Vertex),     &cubeVertices[0].x);
        glTexCoordPointer(2,GL_FLOAT,       sizeof(Vertex),     &cubeVertices[0].u);

        
        glDrawArrays( GL_QUADS, 0, 24 );

        glLoadMatrixf(matVP.data());

        GLfloat ambient_lightModel[] = { 1, 1, 1, 1.0f };
        glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient_lightModel );
        glBindTexture(GL_TEXTURE_2D,_texGround);
        _terrain.render();

    }

    virtual LRESULT events(HWND hWnd,UINT msgId, WPARAM wParam, LPARAM lParam)
    {
        switch (msgId)
        {
        case WM_SIZE:
            {
                if (::IsWindow(hWnd))
                {
                    RECT    rt;
                    GetClientRect(_hWnd,&rt);
                    int     w   =   rt.right - rt.left;
                    int     h   =   rt.bottom - rt.top;
                    glViewport(0,0,w ,h );
                    _camera.setView(w,h);
                }
            }
            break;
        case WM_LBUTTONDOWN:
            {
                _bDownFlag  =   true;
                _mouseDown  =   int2(LOWORD(lParam),HIWORD(lParam));

                CELL::Ray   ray     =   _camera.createRayFromScreen(_mouseDown.x,_mouseDown.y);
                float3      orth    =   ray.getOrigin();
                float       tm      =   (orth.y  + 1)/ray.getDirection().y;
                float3      c       =   ray.getOrigin() + abs(tm) * ray.getDirection();
                _moveTo =   c;
            }
            break;
        case WM_LBUTTONUP:
            {
                _bDownFlag  =   false;
            }
            break;

        case WM_MOUSEWHEEL:
            {
                int delta   =   (short)HIWORD(wParam);
                if (delta > 0)
                {
                    _camera.setRadius(_camera.getRadius() * 1.2f);
                }
                else
                {
                    _camera.setRadius(_camera.getRadius() * 0.8f);
                }
            }
            break;

        case WM_MOUSEMOVE:
            {
                if (_bDownFlag)
                {
                    int2    mouseCur    =  int2(LOWORD(lParam),HIWORD(lParam));
                    float   xOffset     =  mouseCur.x - _mouseDown.x;
                    _mouseDown  =   mouseCur;
                    _camera.rotateY(xOffset * 0.5f);
                }
            }
            break;
        case WM_KEYDOWN:
            {
                switch (wParam)
                {
                case VK_LEFT:
                    _rolePos.x  -=  0.1;
                    break;
                case VK_RIGHT:
                    _rolePos.x  +=  0.1;
                    break;
                case  VK_UP:
                    _rolePos.z  -=  0.1;
                    break;
                case VK_DOWN:
                    _rolePos.z  +=  0.1;
                    break;

                }
            }
            break;
        }
        return  __super::events(hWnd,msgId,wParam,lParam);
    }
};

int __stdcall WinMain( 
                      HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, 
                      int nShowCmd
                      )
{

    SamplerTerrain    instance;
    instance.main(800,600);

    return  0;
}
#pragma once


struct  TerrainVert
{
    float   x,y,z;
    float   nx,ny,nz;
    float   u,v;
    float   r,g,b,a;
    float   fog;
};


#define MAP_SIZE    1024
class Terrain
{
public:
    typedef std::vector<TerrainVert>    ArrayVertex;
    typedef std::vector<unsigned short> ArrayIndex;
public:
    ArrayVertex _vertex;
    ArrayIndex  _index;
    int         _drawSize;

public:

    Terrain(void)
    {
    }

    ~Terrain(void)
    {
    }


    bool    loadHeight(const char* fileName,BYTE* pHeightMap,int w,int h)
    {
        FILE*   pFile   =   fopen( fileName, "rb" );
        if ( pFile == NULL )	
        {
            return  false;
        }
        fread( pHeightMap, 1, w * h, pFile );
        fclose(pFile);
        return  true;
        
    }
   
    float   readHeight(int x,int y,const BYTE* data)
    {
        x = x % MAP_SIZE;
        y = y % MAP_SIZE;

        return (float)data[x + (y * MAP_SIZE)];
    }

    float   readFog(int x,int y,const BYTE* data)
    {
        float h = readHeight(x,y,data);
        if (h > 120)
        {
            return  0;
        }
        return   (120 - h);
    }

    float    readColor(int x,int y,const BYTE* data)
    {
       return -0.15f + (readHeight( x, y,data ) / 256.0f);
    }

    
    float3  computeNomal(TerrainVert& v1, TerrainVert& v2, TerrainVert& v3)
    {
          float3    f1(v2.x - v1.x,    v2.y - v1.y,    v2.z - v1.z);
          float3    f2(v3.x - v1.x,    v3.y - v1.y,    v3.z - v1.z);
          return    normalize(cross(f1, f2));
    }

    void    setup(float w,float h)
    {
        int     step    =   8;
       
        BYTE*   data    =   new BYTE[MAP_SIZE * MAP_SIZE];
        loadHeight("Terrain.raw",data,MAP_SIZE,MAP_SIZE);
        
        /**
        *   产生顶点数据
        */
        for (int z = 0 ; z <= MAP_SIZE ; z += step)
        {
            for (int x = 0 ; x <= MAP_SIZE ; x += step)
            {
                TerrainVert vert0   =   {x, readHeight(x,z,data),  z, 0,0,0,1};
                vert0.x     -=  MAP_SIZE* 0.5f;
                vert0.z     -=  MAP_SIZE* 0.5f;
                vert0.r     =   1;
                vert0.g     =   1;
                vert0.b     =   1;
                vert0.a     =   1;
                vert0.u     =   float(x)/MAP_SIZE;
                vert0.v     =   float(z)/MAP_SIZE;
                vert0.fog   =   readFog(x,z,data);

                _vertex.push_back(vert0);
            }
        }

        delete  []data;

        /**
        *   计算索引数据
        */
        size_t  col =   int(w/step + 0.5f) + 1;
        size_t  row =   int(h/step + 0.5f) + 1;

        for (size_t r = 0 ;r < row - 1 ; ++ r)
        {
            for (size_t i = 0 ; i < col - 1 ; ++ i)
            {
                _index.push_back((r + 0) * col + i);
                _index.push_back((r + 1) * col + i);
                _index.push_back((r + 0) * col + i + 1);

                _index.push_back((r + 1) * col + i);
                _index.push_back((r + 0) * col + i + 1);
                _index.push_back((r + 1) * col + i + 1);
            }
        }

        /**
        *   计算法线
        */
        for (size_t i = 0 ;i < _index.size() ; i+= 3)
        {
            TerrainVert&    v0  =   _vertex[_index[i + 0]];
            TerrainVert&    v1  =   _vertex[_index[i + 1]];
            TerrainVert&    v2  =   _vertex[_index[i + 2]];
            float3          nor =   computeNomal(v0,v1,v2);

            v0.nx   =   nor.x;
            v0.ny   =   nor.y;
            v0.nz   =   nor.z;

            v1.nx   =   nor.x;
            v1.ny   =   nor.y;
            v1.nz   =   nor.z;

            v2.nx   =   nor.x;
            v2.ny   =   nor.y;
            v2.nz   =   nor.z;
        }
    }

    void    render()
    {
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_FOG_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(TerrainVert),     &_vertex[0].x);
        glNormalPointer(GL_FLOAT,           sizeof(TerrainVert),     &_vertex[0].nx);
        glColorPointer(4,GL_FLOAT,          sizeof(TerrainVert),     &_vertex[0].r);
        glTexCoordPointer(2,GL_FLOAT,       sizeof(TerrainVert),     &_vertex[0].u);
        glFogCoordPointer(GL_FLOAT,         sizeof(TerrainVert),     &_vertex[0].fog);

        glDrawElements(GL_TRIANGLES,_index.size(),GL_UNSIGNED_SHORT,&_index.front());

        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
        glDisableClientState(GL_FOG_COORD_ARRAY);


    }
};
  • 运行:













3月5日

  • 地形定点雾化处理-云雾山2
添加多纹理支持,让地形看起来更加真实

lessonA07.cpp更新render()

 virtual void    render()
    {
#define M_PI (3.14159265358979323846)
       

        float   size    =   100;

        Vertex cubeVertices[] =
        {
            {  -1.0f,-1.0f, 1.0f    ,0.3f,  0.3f },
            {  1.0f,-1.0f, 1.0f     ,0.5f,  0.3f },
            {  1.0f, 1.0f, 1.0f     ,0.5f,  0.8f },
            { -1.0f, 1.0f, 1.0f     ,0.3f,  0.8f },

            {  -1.0f,-1.0f,-1.0f    ,0,  0 },
            {  -1.0f, 1.0f,-1.0f    ,1,  0 },
            {  1.0f, 1.0f,-1.0f     ,1,  1 },
            {  1.0f,-1.0f,-1.0f     ,0,  1 },

            {  -1.0f, 1.0f,-1.0f    ,0,  0 },
            {  -1.0f, 1.0f, 1.0f    ,1,  0 },
            {  1.0f, 1.0f, 1.0f     ,1,  1 },
            {  1.0f, 1.0f,-1.0f     ,0,  1 },

            {  -1.0f,-1.0f,-1.0f    ,0,  0 },
            {  1.0f,-1.0f,-1.0f     ,1,  0 },
            {  1.0f,-1.0f, 1.0f     ,1,  1 },
            {  -1.0f,-1.0f, 1.0f    ,0,  1 },

            {  1.0f,-1.0f,-1.0f ,0,  0 },
            {  1.0f, 1.0f,-1.0f ,1,  0 },
            {  1.0f, 1.0f, 1.0f ,1,  1 },
            {  1.0f,-1.0f, 1.0f ,0,  1 },

            {  -1.0f,-1.0f,-1.0f ,0,  0 },
            {  -1.0f,-1.0f, 1.0f ,1,  0 },
            {  -1.0f, 1.0f, 1.0f ,1,  1 },
            {  -1.0f, 1.0f,-1.0f ,0,  1 },

//! 地面数据

            {  -size, -1,    -size       ,0,  0 },
            {  -size, -1,    size        ,100,  0 },
            {  size,  -1,     size        ,100,  100 },
            {  size,  -1,     -size       ,0,  100 },
        };

        //! 指定以下的操作针对投影矩阵
        glMatrixMode(GL_MODELVIEW);

        _camera.perspective(60,float(_width)/float(_height),0.1f,10000.0f);
        
        float3  dir =   normalize(_moveTo - _rolePos);

        if (length(_moveTo - _rolePos) < 1)
        {
            _rolePos    =   _moveTo;
        }
        else
        {
            _rolePos    +=  dir * (10.0f/60.0f);
        }

        _camera.updateLookat(_rolePos);
        //! 摄像机更新
        _camera.update();

        matrix4 matVP  =   _camera.getMVP();
        glLoadMatrixf(matVP.data());
        
        //! 产生一个矩阵
        glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

        glBindTexture(GL_TEXTURE_2D,_texture);

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(Vertex),     &cubeVertices[0].x);
        glTexCoordPointer(2,GL_FLOAT,       sizeof(Vertex),     &cubeVertices[0].u);

        
        glDrawArrays( GL_QUADS, 0, 24 );

        glLoadMatrixf(matVP.data());

        GLfloat ambient_lightModel[] = { 1, 1, 1, 1.0f };
        glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient_lightModel );

		//多纹理操作
		glClientActiveTexture(GL_TEXTURE0);
		glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,_terrainTex);

		glClientActiveTexture(GL_TEXTURE1);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texDetail);
        
		
		glDisable(GL_LIGHTING);
		_terrain.render();

    }
#pragma once


struct  TerrainVert
{
    float   x,y,z;
    float   nx,ny,nz;
    float   u,v;
    float   u1,v1;
    float   r,g,b,a;
    float   fog;
};


#define MAP_SIZE    1024
class Terrain
{
public:
    typedef std::vector<TerrainVert>    ArrayVertex;
    typedef std::vector<unsigned short> ArrayIndex;
public:
    ArrayVertex _vertex;
    ArrayIndex  _index;
    int         _drawSize;

public:

    Terrain(void)
    {
    }

    ~Terrain(void)
    {
    }


    bool    loadHeight(const char* fileName,BYTE* pHeightMap,int w,int h)
    {
        FILE*   pFile   =   fopen( fileName, "rb" );
        if ( pFile == NULL )	
        {
            return  false;
        }
        fread( pHeightMap, 1, w * h, pFile );
        fclose(pFile);
        return  true;
        
    }
   
    float   readHeight(int x,int y,const BYTE* data)
    {
        x = x % MAP_SIZE;
        y = y % MAP_SIZE;

        return (float)data[x + (y * MAP_SIZE)];
    }

    float   readFog(int x,int y,const BYTE* data)
    {
        float h = readHeight(x,y,data);
        if (h > 120)
        {
            return  0;
        }
        return   (120 - h);
    }

    float    readColor(int x,int y,const BYTE* data)
    {
       return -0.15f + (readHeight( x, y,data ) / 256.0f);
    }

    
    float3  computeNomal(TerrainVert& v1, TerrainVert& v2, TerrainVert& v3)
    {
          float3    f1(v2.x - v1.x,    v2.y - v1.y,    v2.z - v1.z);
          float3    f2(v3.x - v1.x,    v3.y - v1.y,    v3.z - v1.z);
          return    normalize(cross(f1, f2));
    }

    void    setup(float w,float h)
    {
        int     step    =   8;
       
        BYTE*   data    =   new BYTE[MAP_SIZE * MAP_SIZE];
        loadHeight("Terrain.raw",data,MAP_SIZE,MAP_SIZE);
        
        /**
        *   产生顶点数据
        */
        for (int z = 0 ; z <= MAP_SIZE ; z += step)
        {
            for (int x = 0 ; x <= MAP_SIZE ; x += step)
            {
                TerrainVert vert0   =   {x, readHeight(x,z,data),  z, 0,0,0,1};
                vert0.x     -=  MAP_SIZE* 0.5f;
                vert0.z     -=  MAP_SIZE* 0.5f;
                vert0.r     =   1;
                vert0.g     =   1;
                vert0.b     =   1;
                vert0.a     =   1;
                vert0.u     =   float(x)/MAP_SIZE;
                vert0.v     =   float(z)/MAP_SIZE;

				vert0.u1    =   vert0.u * 20;
				vert0.v1    =   vert0.v * 20;

                vert0.fog   =   readFog(x,z,data);

                _vertex.push_back(vert0);
            }
        }

        delete  []data;

        /**
        *   计算索引数据
        */
        size_t  col =   int(w/step + 0.5f) + 1;
        size_t  row =   int(h/step + 0.5f) + 1;

        for (size_t r = 0 ;r < row - 1 ; ++ r)
        {
            for (size_t i = 0 ; i < col - 1 ; ++ i)
            {
                _index.push_back((r + 0) * col + i);
                _index.push_back((r + 1) * col + i);
                _index.push_back((r + 0) * col + i + 1);

                _index.push_back((r + 1) * col + i);
                _index.push_back((r + 0) * col + i + 1);
                _index.push_back((r + 1) * col + i + 1);
            }
        }

        /**
        *   计算法线
        */
        for (size_t i = 0 ;i < _index.size() ; i+= 3)
        {
            TerrainVert&    v0  =   _vertex[_index[i + 0]];
            TerrainVert&    v1  =   _vertex[_index[i + 1]];
            TerrainVert&    v2  =   _vertex[_index[i + 2]];
            float3          nor =   computeNomal(v0,v1,v2);

            v0.nx   =   nor.x;
            v0.ny   =   nor.y;
            v0.nz   =   nor.z;

            v1.nx   =   nor.x;
            v1.ny   =   nor.y;
            v1.nz   =   nor.z;

            v2.nx   =   nor.x;
            v2.ny   =   nor.y;
            v2.nz   =   nor.z;
        }
    }

    void    render()
    {
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_FOG_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(TerrainVert),     &_vertex[0].x);
        glNormalPointer(GL_FLOAT,           sizeof(TerrainVert),     &_vertex[0].nx);
        glColorPointer(4,GL_FLOAT,          sizeof(TerrainVert),     &_vertex[0].r);

		glClientActiveTexture(GL_TEXTURE0);//激活
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);//启动
        glTexCoordPointer(2,GL_FLOAT,       sizeof(TerrainVert),     &_vertex[0].u);//告诉数据
        

        glClientActiveTexture(GL_TEXTURE1);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(2,GL_FLOAT,       sizeof(TerrainVert),     &_vertex[0].u1);
		

		glFogCoordPointer(GL_FLOAT,         sizeof(TerrainVert),     &_vertex[0].fog);

        glDrawElements(GL_TRIANGLES,_index.size(),GL_UNSIGNED_SHORT,&_index.front());

        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
        glDisableClientState(GL_FOG_COORD_ARRAY);


    }
};
  • 运行:













3月6日

  • 地形漫游-第一人称摄像机对地形的漫游
解决第一人称摄像机漫游不会陷下去:
读出来摄像机所在位置地形的高度,重新设置摄像机的y(一定在地形上面)
#pragma once

#include "CELLMath.hpp"
using namespace CELL;
class Camera
{

public:
    float3  _eye;
    float3  _lookat;
    //! 定义了摄像机的y轴
    float3  _up;
    float3  _right;
    float   _speed;
    matrix4 _matView;
    matrix4 _matProj;
    float2  _viewSize;

public:

    Camera(void)
    {
        _eye    =   float3(0,0,10);
        _lookat =   float3(0,0,0);
        _up     =   float3(0,1,0);
        _right  =   float3(1,0,0);
        _speed  =   2.0f;
    }
    matrix4 getMVP()
    {
        return  _matProj * _matView;
    }
    void    perspective(float fovy, float aspect, float zNear, float zFar)
    {
        _matProj    =   CELL::perspective(fovy,aspect,zNear,zFar);
    }

    /**
    *   窗口坐标转化为世界坐标
    */
    bool    unProject( const float4& screen, float4& world )
    {
        float4 v;
        v.x =   screen.x;
        v.y =   screen.y;
        v.z =   screen.z;
        v.w =   1.0;

        // map from viewport to 0 - 1
        v.x =   (v.x) /_viewSize.x;
        v.y =   (_viewSize.y - v.y) /_viewSize.y;
        //v.y = (v.y - _viewPort.Y) / _viewPort.Height;

        // map to range -1 to 1
        v.x =   v.x * 2.0f - 1.0f;
        v.y =   v.y * 2.0f - 1.0f;
        v.z =   v.z * 2.0f - 1.0f;

        CELL::matrix4  inverse = (_matProj * _matView ).inverse();

        v   =   v * inverse;
        if (v.w == 0.0f)
        {
            return false;
        }
        world   =   v / v.w;
        return true;
    }


    Ray     createRayFromScreen(int x,int y)
    {
        float4  minWorld;
        float4  maxWorld;

        float4  screen(float(x),float(y),0,1);
        float4  screen1(float(x),float(y),1,1);

        unProject(screen,minWorld);
        unProject(screen1,maxWorld);
        Ray     ray;
        ray.setOrigin(float3(minWorld.x,minWorld.y,minWorld.z));

        float3  dir(maxWorld.x - minWorld.x,maxWorld.y - minWorld.y, maxWorld.z - minWorld.z);
        ray.setDirection(normalize(dir));
        return  ray;
    }
    void    setView(int x,int y)
    {
        _viewSize.x =   x;
        _viewSize.y =   y;
    }
    void    moveLeft()
    {
        _eye    -=  normalize(_right) * _speed;
        _lookat -=  normalize(_right) * _speed;
    }
    void    moveRight()
    {
        _eye    +=  normalize(_right) * _speed;
        _lookat +=  normalize(_right) * _speed;
    }

    void    moveFront()
    {
        float3  dir =   normalize(_lookat - _eye);
        _eye    +=  dir * _speed; //看的方向*速度
        _lookat +=  dir * _speed;

    }
    void    moveBack()
    {
        float3  dir =   normalize(_lookat - _eye);
        _eye    -=  dir * _speed;
        _lookat +=  dir * _speed;
    }

    void    update()
    {
        _matView    =   lookAt(_eye,_lookat,_up);
    }
    /*更新摄像机的 Y*/  
    void    updateH(float height)
    {
        float   offset  =   height - _eye.y;
        _eye.y      =   height;  
        _lookat.y   +=  offset;
    }
   
    void    rotateY(float angle)
    {
        float3  dir =   normalize(_lookat - _eye);
        float   len =   length(_lookat - _eye);

        float3  dir1=   CELL::rotateY(dir,angle);

        _lookat =   _eye + dir1 * len;

        _right  =   normalize(cross(dir1 , _up));
    }
    virtual ~Camera(void)
    {
    }
};

3月8日

//lessonA08.cpp
//新增功能:投影转化
#include <windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera.h"
#include <vector>
#include "Terrain.hpp"
using namespace CELL;

struct Vertex
{ 
    float x, y, z;
    float u, v;
};
class   SamplerTerrain :public OpenGLWindow
{
    GLuint  _texture;

    GLuint  _texGround;
    GLuint  _terrainTex;

	GLuint  _texDetail;

    Camera  _camera;
    int2    _mouseDown;
    bool    _bDownFlag;


    float3  _rolePos;
    float3  _moveTo;
    Terrain _terrain;
public:
    SamplerTerrain() 
    {
        _bDownFlag  =   false;
        _rolePos    =   float3(0,0,0);
        _moveTo     =   _rolePos;
    }         
    /**
    *   使用FreeImage加载图片
    */
    unsigned        createTextureFromImage(const char* fileName)
    {
        //1 获取图片格式
        FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
        if (fifmt == FIF_UNKNOWN)
        {
            return  0;
        }
        //2 加载图片
        FIBITMAP    *dib = FreeImage_Load(fifmt, fileName,0);
     
        FREE_IMAGE_COLOR_TYPE type    =   FreeImage_GetColorType(dib);
      
        //! 获取数据指针
        FIBITMAP*   temp    =   dib;
        dib =   FreeImage_ConvertTo32Bits(dib);
                FreeImage_Unload(temp);

        BYTE*   pixels =   (BYTE*)FreeImage_GetBits(dib);
        int     width   =   FreeImage_GetWidth(dib);
        int     height  =   FreeImage_GetHeight(dib);

        for (int i = 0 ;i < width * height * 4 ; i+=4 )
        {
            BYTE temp       =   pixels[i];
            pixels[i]       =   pixels[i + 2];
            pixels[i + 2]   =   temp;
        }

        unsigned    res =   createTexture(width,height,pixels);
        FreeImage_Unload(dib);
        return      res;
    }

    unsigned        createTexture(int w,int h,const void* data)
    {
        unsigned    texId;
        glGenTextures(1,&texId);
        glBindTexture(GL_TEXTURE_2D,texId);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);

        return  texId;
    }

    virtual void    onInitGL()
    {
        _texture    =   createTextureFromImage("2.jpg");
        _texGround  =   createTextureFromImage("1.jpg");
        _terrainTex =   createTextureFromImage("Terrain.bmp");
        
		_texDetail  =   createTextureFromImage("Detail.bmp");

		_terrain.setup(1024,1024);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);

        GLfloat diffuse_light0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
        GLfloat position_light0[] = { 0, 10, 0, 0.0f };
        glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse_light0 );
        glLightfv( GL_LIGHT0, GL_POSITION, position_light0 );

        float fogColor[4] = {0.8f, 0.8f, 0.8f, 1.0f};

        glEnable(GL_FOG);   
        glFogi(GL_FOG_MODE, GL_LINEAR);	
        glFogfv(GL_FOG_COLOR, fogColor);
        glFogf(GL_FOG_START, 0.0);
        glFogf(GL_FOG_END, 50.0);

        glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);

    }
    virtual void    render()
    {
#define M_PI (3.14159265358979323846)
       

        float   size    =   100;

        Vertex cubeVertices[] =
        {
            {  -1.0f,-1.0f, 1.0f    ,0.3f,  0.3f },
            {  1.0f,-1.0f, 1.0f     ,0.5f,  0.3f },
            {  1.0f, 1.0f, 1.0f     ,0.5f,  0.8f },
            { -1.0f, 1.0f, 1.0f     ,0.3f,  0.8f },

            {  -1.0f,-1.0f,-1.0f    ,0,  0 },
            {  -1.0f, 1.0f,-1.0f    ,1,  0 },
            {  1.0f, 1.0f,-1.0f     ,1,  1 },
            {  1.0f,-1.0f,-1.0f     ,0,  1 },

            {  -1.0f, 1.0f,-1.0f    ,0,  0 },
            {  -1.0f, 1.0f, 1.0f    ,1,  0 },
            {  1.0f, 1.0f, 1.0f     ,1,  1 },
            {  1.0f, 1.0f,-1.0f     ,0,  1 },

            {  -1.0f,-1.0f,-1.0f    ,0,  0 },
            {  1.0f,-1.0f,-1.0f     ,1,  0 },
            {  1.0f,-1.0f, 1.0f     ,1,  1 },
            {  -1.0f,-1.0f, 1.0f    ,0,  1 },

            {  1.0f,-1.0f,-1.0f ,0,  0 },
            {  1.0f, 1.0f,-1.0f ,1,  0 },
            {  1.0f, 1.0f, 1.0f ,1,  1 },
            {  1.0f,-1.0f, 1.0f ,0,  1 },

            {  -1.0f,-1.0f,-1.0f ,0,  0 },
            {  -1.0f,-1.0f, 1.0f ,1,  0 },
            {  -1.0f, 1.0f, 1.0f ,1,  1 },
            {  -1.0f, 1.0f,-1.0f ,0,  1 },

//! 地面数据

            {  -size, -1,    -size       ,0,  0 },
            {  -size, -1,    size        ,100,  0 },
            {  size,  -1,     size        ,100,  100 },
            {  size,  -1,     -size       ,0,  100 },
        };

        //! 指定以下的操作针对投影矩阵
        glMatrixMode(GL_MODELVIEW);

        _camera.perspective(60,float(_width)/float(_height),0.1f,10000.0f);
        
        float3  dir =   normalize(_moveTo - _rolePos);

        if (length(_moveTo - _rolePos) < 1)
        {
            _rolePos    =   _moveTo;
        }
        else
        {
            _rolePos    +=  dir * (10.0f/60.0f);
        }
        float height = _terrain.calcHeight(_camera._eye.x,_camera._eye.z,_terrain._data) + 5;
		_camera.updateH(height);
        
        //! 摄像机更新
        _camera.update();

        matrix4 matVP  =   _camera.getMVP();
        glLoadMatrixf(matVP.data());
        
        //! 产生一个矩阵
        glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

        glBindTexture(GL_TEXTURE_2D,_texture);

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(Vertex),     &cubeVertices[0].x);
        glTexCoordPointer(2,GL_FLOAT,       sizeof(Vertex),     &cubeVertices[0].u);

        
        glDrawArrays( GL_QUADS, 0, 24 );

        glLoadMatrixf(matVP.data());

        GLfloat ambient_lightModel[] = { 1, 1, 1, 1.0f };
        glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient_lightModel );

		//多纹理操作
		glClientActiveTexture(GL_TEXTURE0);
		glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,_terrainTex);

		glClientActiveTexture(GL_TEXTURE1);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texDetail);
        
		
		glDisable(GL_LIGHTING);
		_terrain.render();

    }

    virtual LRESULT events(HWND hWnd,UINT msgId, WPARAM wParam, LPARAM lParam)
    {
        switch (msgId)
        {
        case WM_SIZE:
            {
                if (::IsWindow(hWnd))
                {
                    RECT    rt;
                    GetClientRect(_hWnd,&rt);
                    int     w   =   rt.right - rt.left;
                    int     h   =   rt.bottom - rt.top;
                    glViewport(0,0,w ,h );
                    _camera.setView(w,h);
                }
            }
            break;
        case WM_LBUTTONDOWN:
            {
                _bDownFlag  =   true;
                _mouseDown  =   int2(LOWORD(lParam),HIWORD(lParam));

                /*CELL::Ray   ray     =   _camera.createRayFromScreen(_mouseDown.x,_mouseDown.y);
                float3      orth    =   ray.getOrigin();
                float       tm      =   (orth.y  + 1)/ray.getDirection().y;
                float3      c       =   ray.getOrigin() + abs(tm) * ray.getDirection();
                _moveTo =   c;*/
            }
            break;
        case WM_LBUTTONUP:
            {
                _bDownFlag  =   false;
            }
            break;

        case WM_MOUSEWHEEL:
            {
              
            }
            break;

        case WM_MOUSEMOVE:
            {
                if (_bDownFlag)
                {
                    int2    mouseCur    =  int2(LOWORD(lParam),HIWORD(lParam));
                    float   xOffset     =  mouseCur.x - _mouseDown.x;
                    _mouseDown  =   mouseCur;
                    _camera.rotateY(xOffset * 0.5f);
                }
            }
            break;
        case WM_KEYDOWN:
            {
                switch (wParam)
                {
                case VK_LEFT:
                    _camera.moveLeft();
                    break;
                case VK_RIGHT:
                    _camera.moveRight();
                    break;
                case  VK_UP:
                    _camera.moveFront();
                    break;
                case VK_DOWN:
                    _camera.moveBack();
                    break;

                }
            }
            break;
        }
        return  __super::events(hWnd,msgId,wParam,lParam);
    }
};

int __stdcall WinMain( 
                      HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, 
                      int nShowCmd
                      )
{

    SamplerTerrain    instance;
    instance.main(800,600);

    return  0;
}
//Terrain.hpp里添加下面函数

    //根据给定的x,z世界坐标,计算出来所在位置的高度
	float calcHeight(float x,float z,BYTE* data)
	{
     float startX = -MAP_SIZE * 0.5f;
     float startY = -MAP_SIZE * 0.5f;
     float offsetX = x - startX;
     float offsetZ = z - startY;
   
	 if (offsetX < 0)
	 {
		 offsetX = 0;
	 }
	 if (offsetZ < 0)
	 {
		 offsetZ = 0;
	 }
	 if (offsetX >= MAP_SIZE)
	 {
		 offsetX = MAP_SIZE - 1;
	 }
	 if (offsetZ >= MAP_SIZE)
	 {
		 offsetZ = MAP_SIZE - 1;
	 }
    
	 int posX = (int)offsetX;
	 int posZ = (int)offsetZ;
	 return readHeight(posX,posZ,data);
	}
  • 运行:













3月13日

  • 地形漫游-第三人称摄像机-角色控制
//lesson206.cpp
//新增功能:投影转化
#include <windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
#include "Terrain.hpp"
using namespace CELL;

struct Vertex
{ 
    float x, y, z;
    float u, v;
};
class   SamplerTerrain :public OpenGLWindow
{
    GLuint  _texture;

    GLuint  _texGround;
    GLuint  _terrainTex;

	GLuint  _texDetail;

    Camera3rd  _camera;//第三人称
    int2    _mouseDown;
    bool    _bDownFlag;


    float3  _rolePos;
    float3  _moveTo;
    Terrain _terrain;
public:
    SamplerTerrain() 
    {
        _bDownFlag  =   false;
        _rolePos    =   float3(0,0,0);
        _moveTo     =   _rolePos;
    }         
    /**
    *   使用FreeImage加载图片
    */
    unsigned        createTextureFromImage(const char* fileName)
    {
        //1 获取图片格式
        FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
        if (fifmt == FIF_UNKNOWN)
        {
            return  0;
        }
        //2 加载图片
        FIBITMAP    *dib = FreeImage_Load(fifmt, fileName,0);
     
        FREE_IMAGE_COLOR_TYPE type    =   FreeImage_GetColorType(dib);
      
        //! 获取数据指针
        FIBITMAP*   temp    =   dib;
        dib =   FreeImage_ConvertTo32Bits(dib);
                FreeImage_Unload(temp);

        BYTE*   pixels =   (BYTE*)FreeImage_GetBits(dib);
        int     width   =   FreeImage_GetWidth(dib);
        int     height  =   FreeImage_GetHeight(dib);

        for (int i = 0 ;i < width * height * 4 ; i+=4 )
        {
            BYTE temp       =   pixels[i];
            pixels[i]       =   pixels[i + 2];
            pixels[i + 2]   =   temp;
        }

        unsigned    res =   createTexture(width,height,pixels);
        FreeImage_Unload(dib);
        return      res;
    }

    unsigned        createTexture(int w,int h,const void* data)
    {
        unsigned    texId;
        glGenTextures(1,&texId);
        glBindTexture(GL_TEXTURE_2D,texId);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);

        return  texId;
    }

    virtual void    onInitGL()
    {
        _texture    =   createTextureFromImage("2.jpg");
        _texGround  =   createTextureFromImage("1.jpg");
        _terrainTex =   createTextureFromImage("Terrain.bmp");
        
		_texDetail  =   createTextureFromImage("Detail.bmp");

		_terrain.setup(1024,1024);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);

        GLfloat diffuse_light0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
        GLfloat position_light0[] = { 0, 10, 0, 0.0f };
        glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse_light0 );
        glLightfv( GL_LIGHT0, GL_POSITION, position_light0 );

        float fogColor[4] = {0.8f, 0.8f, 0.8f, 1.0f};

        glEnable(GL_FOG);   
        glFogi(GL_FOG_MODE, GL_LINEAR);	
        glFogfv(GL_FOG_COLOR, fogColor);
        glFogf(GL_FOG_START, 0.0);
        glFogf(GL_FOG_END, 50.0);

        glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);

    }
    virtual void    render()
    {
#define M_PI (3.14159265358979323846)
       

        float   size    =   100;

        Vertex cubeVertices[] =
        {
            {  -1.0f,-1.0f, 1.0f    ,0.3f,  0.3f },
            {  1.0f,-1.0f, 1.0f     ,0.5f,  0.3f },
            {  1.0f, 1.0f, 1.0f     ,0.5f,  0.8f },
            { -1.0f, 1.0f, 1.0f     ,0.3f,  0.8f },

            {  -1.0f,-1.0f,-1.0f    ,0,  0 },
            {  -1.0f, 1.0f,-1.0f    ,1,  0 },
            {  1.0f, 1.0f,-1.0f     ,1,  1 },
            {  1.0f,-1.0f,-1.0f     ,0,  1 },

            {  -1.0f, 1.0f,-1.0f    ,0,  0 },
            {  -1.0f, 1.0f, 1.0f    ,1,  0 },
            {  1.0f, 1.0f, 1.0f     ,1,  1 },
            {  1.0f, 1.0f,-1.0f     ,0,  1 },

            {  -1.0f,-1.0f,-1.0f    ,0,  0 },
            {  1.0f,-1.0f,-1.0f     ,1,  0 },
            {  1.0f,-1.0f, 1.0f     ,1,  1 },
            {  -1.0f,-1.0f, 1.0f    ,0,  1 },

            {  1.0f,-1.0f,-1.0f ,0,  0 },
            {  1.0f, 1.0f,-1.0f ,1,  0 },
            {  1.0f, 1.0f, 1.0f ,1,  1 },
            {  1.0f,-1.0f, 1.0f ,0,  1 },

            {  -1.0f,-1.0f,-1.0f ,0,  0 },
            {  -1.0f,-1.0f, 1.0f ,1,  0 },
            {  -1.0f, 1.0f, 1.0f ,1,  1 },
            {  -1.0f, 1.0f,-1.0f ,0,  1 },

//! 地面数据

            {  -size, -1,    -size       ,0,  0 },
            {  -size, -1,    size        ,100,  0 },
            {  size,  -1,     size        ,100,  100 },
            {  size,  -1,     -size       ,0,  100 },
        };

        //! 指定以下的操作针对投影矩阵
        glMatrixMode(GL_MODELVIEW);

        _camera.perspective(60,float(_width)/float(_height),0.1f,10000.0f);
        
        float3  dir =   normalize(_moveTo - _rolePos);
      //鼠标点击移动
      /*  if (length(_moveTo - _rolePos) < 1)
        {
            _rolePos    =   _moveTo;
        }
        else
        {
            _rolePos    +=  dir * (10.0f/60.0f);
        }*/
        float height = _terrain.calcHeight(_camera._eye.x,_camera._eye.z,_terrain._data) + 5;
		_rolePos.y = height;

		_camera.updateLookat(_rolePos);
        
        //! 摄像机更新
        _camera.update();

        matrix4 matVP  =   _camera.getMVP();
        glLoadMatrixf(matVP.data());
        
        //! 产生一个矩阵
        glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

        glBindTexture(GL_TEXTURE_2D,_texture);

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(Vertex),     &cubeVertices[0].x);
        glTexCoordPointer(2,GL_FLOAT,       sizeof(Vertex),     &cubeVertices[0].u);

        
        glDrawArrays( GL_QUADS, 0, 24 );

        glLoadMatrixf(matVP.data());

        GLfloat ambient_lightModel[] = { 1, 1, 1, 1.0f };
        glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient_lightModel );

		//多纹理操作
		glClientActiveTexture(GL_TEXTURE0);
		glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,_terrainTex);

		glClientActiveTexture(GL_TEXTURE1);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texDetail);
        
		
		glDisable(GL_LIGHTING);
		_terrain.render();

    }

    virtual LRESULT events(HWND hWnd,UINT msgId, WPARAM wParam, LPARAM lParam)
    {
        switch (msgId)
        {
        case WM_SIZE:
            {
                if (::IsWindow(hWnd))
                {
                    RECT    rt;
                    GetClientRect(_hWnd,&rt);
                    int     w   =   rt.right - rt.left;
                    int     h   =   rt.bottom - rt.top;
                    glViewport(0,0,w ,h );
                    _camera.setView(w,h);
                }
            }
            break;
        case WM_LBUTTONDOWN:
            {
                _bDownFlag  =   true;
                _mouseDown  =   int2(LOWORD(lParam),HIWORD(lParam));

                /*CELL::Ray   ray     =   _camera.createRayFromScreen(_mouseDown.x,_mouseDown.y);
                float3      orth    =   ray.getOrigin();
                float       tm      =   (orth.y  + 1)/ray.getDirection().y;
                float3      c       =   ray.getOrigin() + abs(tm) * ray.getDirection();
                _moveTo =   c;*/
            }
            break;
        case WM_LBUTTONUP:
            {
                _bDownFlag  =   false;
            }
            break;

        case WM_MOUSEWHEEL:
            {
              
            }
            break;

        case WM_MOUSEMOVE:
            {
                if (_bDownFlag)
                {
                    int2    mouseCur    =  int2(LOWORD(lParam),HIWORD(lParam));
                    float   xOffset     =  mouseCur.x - _mouseDown.x;
                    _mouseDown  =   mouseCur;
                    _camera.rotateY(xOffset * 0.5f);
                }
            }
            break;
        case WM_KEYDOWN:
            {
                switch (wParam)
                {
                case VK_LEFT:
                    _rolePos -= normalize(_camera._right) * float3(2,0,2);//向左向右移动时候用的摄像机的x轴 (*速度)
                    break;
                case VK_RIGHT:
                    _rolePos += normalize(_camera._right) * float3(2,0,2);
                    break;
                case  VK_UP:
					{
						float3 dir = normalize(_camera._lookat - _camera._eye);
						dir.y = 0;
						_rolePos += dir * 2.0f;
					}
                    
					break;
                case VK_DOWN:
					{
						float3 dir = normalize(_camera._lookat - _camera._eye);
						dir.y = 0;
						_rolePos -= dir * 2.0f;
					}
                    break;

                }
            }
            break;
        }
        return  __super::events(hWnd,msgId,wParam,lParam);
    }
};

int __stdcall WinMain( 
                      HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, 
                      int nShowCmd
                      )
{

    SamplerTerrain    instance;
    instance.main(800,600);

    return  0;
}
  • 运行:













3月14日

  • A-lessonA10-地形漫游-第三人称摄像机-鼠标控制
说明图













#pragma once


struct  TerrainVert
{
    float   x,y,z;
    float   nx,ny,nz;
    float   u,v;
    float   u1,v1;
    float   r,g,b,a;
    float   fog;
};

struct Quat
{
	float3 pt0;
	float3 pt1;
};

#define MAP_SIZE    1024
#define STEP 8//步长为8,每隔8个步长产生1个像素
class Terrain
{
public:
    typedef std::vector<TerrainVert>    ArrayVertex;
    typedef std::vector<unsigned short> ArrayIndex;
public:
    ArrayVertex _vertex;
    ArrayIndex  _index;
    int         _drawSize;
	BYTE*       _data;

public:

    Terrain(void)
    {
    }

    ~Terrain(void)
    {
    }


    bool    loadHeight(const char* fileName,BYTE* pHeightMap,int w,int h)
    {
        FILE*   pFile   =   fopen( fileName, "rb" );
        if ( pFile == NULL )	
        {
            return  false;
        }
        fread( pHeightMap, 1, w * h, pFile );
        fclose(pFile);
        return  true;
        
    }
   
    float   readHeight(int x,int y,const BYTE* data)
    {
        x = x % MAP_SIZE;
        y = y % MAP_SIZE;

        return (float)data[x + (y * MAP_SIZE)];
    }

    float   readFog(int x,int y,const BYTE* data)
    {
        float h = readHeight(x,y,data);
        if (h > 120)
        {
            return  0;
        }
        return   (120 - h);
    }

    float    readColor(int x,int y,const BYTE* data)
    {
       return -0.15f + (readHeight( x, y,data ) / 256.0f);
    }

    
    float3  computeNomal(TerrainVert& v1, TerrainVert& v2, TerrainVert& v3)
    {
          float3    f1(v2.x - v1.x,    v2.y - v1.y,    v2.z - v1.z);
          float3    f2(v3.x - v1.x,    v3.y - v1.y,    v3.z - v1.z);
          return    normalize(cross(f1, f2));
    }
    //根据给定的x,z世界坐标,计算出来所在位置的高度
	float calcHeight(float x,float z,BYTE* data)
	{
     float startX = -MAP_SIZE * 0.5f;
     float startY = -MAP_SIZE * 0.5f;
     float offsetX = x - startX;
     float offsetZ = z - startY;
   
	 if (offsetX < 0)
	 {
		 offsetX = 0;
	 }
	 if (offsetZ < 0)
	 {
		 offsetZ = 0;
	 }
	 if (offsetX >= MAP_SIZE)
	 {
		 offsetX = MAP_SIZE - 1;
	 }
	 if (offsetZ >= MAP_SIZE)
	 {
		 offsetZ = MAP_SIZE - 1;
	 }
    
	 int posX = (int)offsetX;
	 int posZ = (int)offsetZ;
	 return readHeight(posX,posZ,data);
	}

	//根据给定的世界坐标的x,z值返回该点所在的两个三角形
	bool calcRect(float x,float z,Quat& rect)
	{
       float startX = -MAP_SIZE * 0.5f;
       float startY = -MAP_SIZE * 0.5f;
	   //计算出来地图图片上的坐标
	   int offsetX = int(x - startX);
       int offsetZ = int(z - startY);

	   //安全监察(保证不越界)
	   if (offsetX < 0)
	   {
		   offsetX = 0;
	   }
	   if (offsetZ < 0)
	   {
		   offsetZ = 0;
	   }
	   if (offsetX >= MAP_SIZE)
	   {
		   offsetX = MAP_SIZE - 1;
	   }
	   if (offsetZ >= MAP_SIZE)
	   {
		   offsetZ = MAP_SIZE - 1;
	   }

	   //计算出来定点位置的索引
	   int col = offsetX/STEP;
	   int row = offsetZ/STEP;
	   int idx0 = (MAP_SIZE/STEP +1)* row + col;//索引号

	   int idx1 = (MAP_SIZE/STEP +1)* (row + 1) +(col + 1);
	   if (idx1 > _vertex.size())
	   {
		   return false;
	   }
	   rect.pt0 = float3(_vertex[idx0].x,_vertex[idx0].y,_vertex[idx0].z);
	   rect.pt1 = float3(_vertex[idx1].x,_vertex[idx1].y,_vertex[idx1].z);

	   return true;

	}
    void    setup(float w,float h)
    {
        int     step    =   STEP;
       
        BYTE*   data    =   new BYTE[MAP_SIZE * MAP_SIZE];
        loadHeight("Terrain.raw",data,MAP_SIZE,MAP_SIZE);
        
        /**
        *   产生顶点数据
        */
        for (int z = 0 ; z <= MAP_SIZE ; z += step)
        {
            for (int x = 0 ; x <= MAP_SIZE ; x += step)
            {
                TerrainVert vert0   =   {x, readHeight(x,z,data),  z, 0,0,0,1};
                vert0.x     -=  MAP_SIZE* 0.5f;
                vert0.z     -=  MAP_SIZE* 0.5f;
                vert0.r     =   1;
                vert0.g     =   1;
                vert0.b     =   1;
                vert0.a     =   1;
                vert0.u     =   float(x)/MAP_SIZE;
                vert0.v     =   float(z)/MAP_SIZE;

				vert0.u1    =   vert0.u * 20;
				vert0.v1    =   vert0.v * 20;

                vert0.fog   =   readFog(x,z,data);

                _vertex.push_back(vert0);
            }
        }

        delete  []data;

        /**
        *   计算索引数据
        */
        size_t  col =   int(w/step + 0.5f) + 1;
        size_t  row =   int(h/step + 0.5f) + 1;

        for (size_t r = 0 ;r < row - 1 ; ++ r)
        {
            for (size_t i = 0 ; i < col - 1 ; ++ i)
            {
                _index.push_back((r + 0) * col + i);
                _index.push_back((r + 1) * col + i);
                _index.push_back((r + 0) * col + i + 1);

                _index.push_back((r + 1) * col + i);
                _index.push_back((r + 0) * col + i + 1);
                _index.push_back((r + 1) * col + i + 1);
            }
        }

        /**
        *   计算法线
        */
        for (size_t i = 0 ;i < _index.size() ; i+= 3)
        {
            TerrainVert&    v0  =   _vertex[_index[i + 0]];
            TerrainVert&    v1  =   _vertex[_index[i + 1]];
            TerrainVert&    v2  =   _vertex[_index[i + 2]];
            float3          nor =   computeNomal(v0,v1,v2);

            v0.nx   =   nor.x;
            v0.ny   =   nor.y;
            v0.nz   =   nor.z;

            v1.nx   =   nor.x;
            v1.ny   =   nor.y;
            v1.nz   =   nor.z;

            v2.nx   =   nor.x;
            v2.ny   =   nor.y;
            v2.nz   =   nor.z;
        }
    }

    void    render()
    {
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnableClientState(GL_FOG_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(TerrainVert),     &_vertex[0].x);
        glNormalPointer(GL_FLOAT,           sizeof(TerrainVert),     &_vertex[0].nx);
        glColorPointer(4,GL_FLOAT,          sizeof(TerrainVert),     &_vertex[0].r);

		glClientActiveTexture(GL_TEXTURE0);//激活
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);//启动
        glTexCoordPointer(2,GL_FLOAT,       sizeof(TerrainVert),     &_vertex[0].u);//告诉数据
        

        glClientActiveTexture(GL_TEXTURE1);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(2,GL_FLOAT,       sizeof(TerrainVert),     &_vertex[0].u1);
		

		glFogCoordPointer(GL_FLOAT,         sizeof(TerrainVert),     &_vertex[0].fog);

        glDrawElements(GL_TRIANGLES,_index.size(),GL_UNSIGNED_SHORT,&_index.front());

        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_NORMAL_ARRAY);
        glDisableClientState(GL_FOG_COORD_ARRAY);


    }
};
//lesson206.cpp
//新增功能:投影转化
#include <windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
#include "Terrain.hpp"
using namespace CELL;

struct Vertex
{ 
    float x, y, z;
    float u, v;
};
class   SamplerTerrain :public OpenGLWindow
{
    GLuint  _texture;

    GLuint  _texGround;
    GLuint  _terrainTex;

	GLuint  _texDetail;

    Camera3rd  _camera;//第三人称
    int2    _mouseDown;
    bool    _bDownFlag;


    float3  _rolePos;
    float3  _moveTo;
    Terrain _terrain;
public:
    SamplerTerrain() 
    {
        _bDownFlag  =   false;
        _rolePos    =   float3(0,0,0);
        _moveTo     =   _rolePos;
    }         
    /**
    *   使用FreeImage加载图片
    */
    unsigned        createTextureFromImage(const char* fileName)
    {
        //1 获取图片格式
        FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
        if (fifmt == FIF_UNKNOWN)
        {
            return  0;
        }
        //2 加载图片
        FIBITMAP    *dib = FreeImage_Load(fifmt, fileName,0);
     
        FREE_IMAGE_COLOR_TYPE type    =   FreeImage_GetColorType(dib);
      
        //! 获取数据指针
        FIBITMAP*   temp    =   dib;
        dib =   FreeImage_ConvertTo32Bits(dib);
                FreeImage_Unload(temp);

        BYTE*   pixels =   (BYTE*)FreeImage_GetBits(dib);
        int     width   =   FreeImage_GetWidth(dib);
        int     height  =   FreeImage_GetHeight(dib);

        for (int i = 0 ;i < width * height * 4 ; i+=4 )
        {
            BYTE temp       =   pixels[i];
            pixels[i]       =   pixels[i + 2];
            pixels[i + 2]   =   temp;
        }

        unsigned    res =   createTexture(width,height,pixels);
        FreeImage_Unload(dib);
        return      res;
    }

    unsigned        createTexture(int w,int h,const void* data)
    {
        unsigned    texId;
        glGenTextures(1,&texId);
        glBindTexture(GL_TEXTURE_2D,texId);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);

        return  texId;
    }

    virtual void    onInitGL()
    {
        _texture    =   createTextureFromImage("2.jpg");
        _texGround  =   createTextureFromImage("1.jpg");
        _terrainTex =   createTextureFromImage("Terrain.bmp");
        
		_texDetail  =   createTextureFromImage("Detail.bmp");

		_terrain.setup(1024,1024);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);

        GLfloat diffuse_light0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
        GLfloat position_light0[] = { 0, 10, 0, 0.0f };
        glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse_light0 );
        glLightfv( GL_LIGHT0, GL_POSITION, position_light0 );

        float fogColor[4] = {0.8f, 0.8f, 0.8f, 1.0f};

        glEnable(GL_FOG);   
        glFogi(GL_FOG_MODE, GL_LINEAR);	
        glFogfv(GL_FOG_COLOR, fogColor);
        glFogf(GL_FOG_START, 0.0);
        glFogf(GL_FOG_END, 50.0);

        glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);

    }
    virtual void    render()
    {
#define M_PI (3.14159265358979323846)
       

        float   size    =   100;

        Vertex cubeVertices[] =
        {
            {  -1.0f,-1.0f, 1.0f    ,0.3f,  0.3f },
            {  1.0f,-1.0f, 1.0f     ,0.5f,  0.3f },
            {  1.0f, 1.0f, 1.0f     ,0.5f,  0.8f },
            { -1.0f, 1.0f, 1.0f     ,0.3f,  0.8f },

            {  -1.0f,-1.0f,-1.0f    ,0,  0 },
            {  -1.0f, 1.0f,-1.0f    ,1,  0 },
            {  1.0f, 1.0f,-1.0f     ,1,  1 },
            {  1.0f,-1.0f,-1.0f     ,0,  1 },

            {  -1.0f, 1.0f,-1.0f    ,0,  0 },
            {  -1.0f, 1.0f, 1.0f    ,1,  0 },
            {  1.0f, 1.0f, 1.0f     ,1,  1 },
            {  1.0f, 1.0f,-1.0f     ,0,  1 },

            {  -1.0f,-1.0f,-1.0f    ,0,  0 },
            {  1.0f,-1.0f,-1.0f     ,1,  0 },
            {  1.0f,-1.0f, 1.0f     ,1,  1 },
            {  -1.0f,-1.0f, 1.0f    ,0,  1 },

            {  1.0f,-1.0f,-1.0f ,0,  0 },
            {  1.0f, 1.0f,-1.0f ,1,  0 },
            {  1.0f, 1.0f, 1.0f ,1,  1 },
            {  1.0f,-1.0f, 1.0f ,0,  1 },

            {  -1.0f,-1.0f,-1.0f ,0,  0 },
            {  -1.0f,-1.0f, 1.0f ,1,  0 },
            {  -1.0f, 1.0f, 1.0f ,1,  1 },
            {  -1.0f, 1.0f,-1.0f ,0,  1 },

//! 地面数据

            {  -size, -1,    -size       ,0,  0 },
            {  -size, -1,    size        ,100,  0 },
            {  size,  -1,     size        ,100,  100 },
            {  size,  -1,     -size       ,0,  100 },
        };

        //! 指定以下的操作针对投影矩阵
        glMatrixMode(GL_MODELVIEW);

        _camera.perspective(60,float(_width)/float(_height),0.1f,10000.0f);
        
        float3  dir =   normalize(_moveTo - _rolePos);
      //鼠标点击移动
      /*  if (length(_moveTo - _rolePos) < 1)
        {
            _rolePos    =   _moveTo;
        }
        else
        {
            _rolePos    +=  dir * (10.0f/60.0f);
        }*/
        float height = _terrain.calcHeight(_camera._eye.x,_camera._eye.z,_terrain._data) + 5;
		_rolePos.y = height;

		_camera.updateLookat(_rolePos);
        
        //! 摄像机更新
        _camera.update();

        matrix4 matVP  =   _camera.getMVP();
        glLoadMatrixf(matVP.data());
        
        //! 产生一个矩阵
        glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

        glBindTexture(GL_TEXTURE_2D,_texture);

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_TEXTURE_2D);

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         sizeof(Vertex),     &cubeVertices[0].x);
        glTexCoordPointer(2,GL_FLOAT,       sizeof(Vertex),     &cubeVertices[0].u);

        
        glDrawArrays( GL_QUADS, 0, 24 );

        glLoadMatrixf(matVP.data());

        GLfloat ambient_lightModel[] = { 1, 1, 1, 1.0f };
        glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient_lightModel );

		//多纹理操作
		glClientActiveTexture(GL_TEXTURE0);
		glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D,_terrainTex);

		glClientActiveTexture(GL_TEXTURE1);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D,_texDetail);
        
		
		glDisable(GL_LIGHTING);
		_terrain.render();

    }

    virtual LRESULT events(HWND hWnd,UINT msgId, WPARAM wParam, LPARAM lParam)
    {
        switch (msgId)
        {
        case WM_SIZE:
            {
                if (::IsWindow(hWnd))
                {
                    RECT    rt;
                    GetClientRect(_hWnd,&rt);
                    int     w   =   rt.right - rt.left;
                    int     h   =   rt.bottom - rt.top;
                    glViewport(0,0,w ,h );
                    _camera.setView(w,h);
                }
            }
            break;
        case WM_LBUTTONDOWN:
            {
                _bDownFlag  =   true;
                _mouseDown  =   int2(LOWORD(lParam),HIWORD(lParam));

                CELL::Ray   ray     =   _camera.createRayFromScreen(_mouseDown.x,_mouseDown.y);
                float3      orth    =   ray.getOrigin();//鼠标按下得到射线
                
				float      tm      =   orth.y/ray.getDirection().y;
				float3      c       =   ray.getOrigin() + abs(tm) * ray.getDirection();//得到跟地面的交点
				
				float3      dir     =   normalize(c - float3(_rolePos.x,0,_rolePos.z));//地面的交点- 当前角色
				float3      start   =   float3(_rolePos.x,0,_rolePos.z);
				float       len     =   CELL::length(start - c);

				bool        ttt     =   true;
				for(float t = 0;t < len + STEP;t += STEP)
				{
					bool flg = false;
					if (t>=len)
					{
						t   = len;
						flg = true;
					}
					float3 cur = start + dir * t;
					Quat rect;
					if(_terrain.calcRect(cur.x,cur.z,rect))
					{
						float3 v0 = rect.pt0;
                        float3 v1 = rect.pt1;
                        float3 v2 = float3(rect.pt0.x,0,rect.pt1.z);
						float3 v3 = float3(rect.pt1.x,0,rect.pt0.z);
					
						float   t       =   0;
						float   u       =   0;
						float   v       =   0;

						//判断三角形是否和射线相交
					    if (intersectTriangle<float>(orth,ray.getDirection(),v0,v1,v2,&t,&u,&v))
					    {
							_moveTo = orth + ray.getDirection() * t;
							ttt     = true;
							break;
					    }
						if (intersectTriangle<float>(orth,ray.getDirection(),v0,v1,v3,&t,&u,&v))
						{
							_moveTo = orth + ray.getDirection() * t;
							ttt     = true;
							break;
						}
					}

				}

                
            }
            break;
        case WM_LBUTTONUP:
            {
                _bDownFlag  =   false;
            }
            break;

        case WM_MOUSEWHEEL:
            {
              
            }
            break;

        case WM_MOUSEMOVE:
            {
                if (_bDownFlag)
                {
                    int2    mouseCur    =  int2(LOWORD(lParam),HIWORD(lParam));
                    float   xOffset     =  mouseCur.x - _mouseDown.x;
                    _mouseDown  =   mouseCur;
                    _camera.rotateY(xOffset * 0.5f);
                }
            }
            break;
        case WM_KEYDOWN:
            {
                switch (wParam)
                {
                case VK_LEFT:
                    _rolePos -= normalize(_camera._right) * float3(2,0,2);//向左向右移动时候用的摄像机的x轴 (*速度)
                    break;
                case VK_RIGHT:
                    _rolePos += normalize(_camera._right) * float3(2,0,2);
                    break;
                case  VK_UP:
					{
						float3 dir = normalize(_camera._lookat - _camera._eye);
						dir.y = 0;
						_rolePos += dir * 2.0f;
					}
                    
					break;
                case VK_DOWN:
					{
						float3 dir = normalize(_camera._lookat - _camera._eye);
						dir.y = 0;
						_rolePos -= dir * 2.0f;
					}
                    break;

                }
            }
            break;
        }
        return  __super::events(hWnd,msgId,wParam,lParam);
    }
};

int __stdcall WinMain( 
                      HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, 
                      int nShowCmd
                      )
{

    SamplerTerrain    instance;
    instance.main(800,600);

    return  0;
}
  • 运行:













3月16日

  • 模型的介绍
软件:3ds Max
 导出格式:(*.3DS:自定义的一种中间文件的交换格式;二进制文本);(*.ASE:文本形式的)(*.DWG、*.DXF测绘、规划用的比较多);(*.SKIN:自己定义)
将.obj文件拖入vs中,
  顶点8个(v)
  uv坐标12个(vt)
  法线坐标8个(vn)
  面的索引(f)(顶点索引/纹理索引/法线索引)
  加载模型数据的库:assimp(assimp.sourceforge.net)、
 assimp开源图形库的使用(https://blog.csdn.net/qq_16756235/article/details/67640405)

3月17日

  • OBJ格式模型的加载
  ①对象里自带渲染函数(绘制函数)②只提供数据,不提供渲染,由外部完成(优势:OBJLoader.hpp除了这个程序能用,另外的[d3d、OpenGL、OpenGLES]绘制也能用,只是绘制的方式不同)
//OBJLoader.hpp
#pragma once

//加载-绘制
#include "CELLMath.hpp"
#include <vector>
class OBJLoader
{
public:
	struct Face
	{
		unsigned int v1,v2,v3;
		unsigned int n1,n2,n3;//法线索引
		unsigned int t1,t2,t3;
	};
public:

	std::vector<CELL::float3> _vertexs;
	std::vector<CELL::float3> _normals;
	std::vector<CELL::float2> _uvs;

	std::vector<Face>           _face;   

public:
	//加载文件
	bool load(const char* fileName)
	{
		FILE* pFile = fopen(fileName,"rt");
		if (pFile == 0)
		{
			return false;
		}

		_vertexs.clear();
		_uvs.clear();
		_normals.clear();
		_face.clear();

		while (feof(pFile) == 0)//如果文件没结束
		{
			char szLine[1024];
			fgets(szLine,sizeof(szLine),pFile);//从pFile读数据,最多读sizeof(szLine)到szLine
			//!顶点数据
			if (szLine[0] == 'v' && szLine[1] == ' ')
			{
				CELL::float3 pos;
				sscanf(szLine,"v  %f %f %f",&pos.x,&pos.y,&pos.z);
				_vertexs.push_back(pos);
			}
			else if(szLine[0] == 'v' && szLine[1] == 't')
			{
				CELL::float2 pos;
				sscanf(szLine,"vt  %f %f",&pos.x,&pos.y);
				_uvs.push_back(pos);
			}
			else if(szLine[0] == 'v' && szLine[1] == 'n')
			{
				CELL::float3 pos;
				sscanf(szLine,"vn  %f %f %f",&pos.x,&pos.y,&pos.z);
				_normals.push_back(pos);
			}
			else if(szLine[0] == 'f' && szLine[1] == ' ')
			{
				Face face;
				sscanf(szLine,
					"f  %d%d%d %d%d%d %d%d%d"
					,&face.v1
					,&face.t1
					,&face.n1

					,&face.v2
					,&face.t2
					,&face.n2

					,&face.v3
					,&face.t3
					,&face.n3);

				_face.push_back(face);
			}
		}
		fclose(pFile);
		return true;
	}

};

3月19日

//lesson801.cpp
#include <Windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
#include "OBJLoader.hpp"
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 

	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int

	GLuint _texGround;

	Camera3rd _camera;
	int2 _mouseDown;
	bool _bDownFlag;//鼠标按下的标志

	float3 _rolePos;
	float3 _moveTo;

public:
	SamplerTexture() 
	{
		_bDownFlag  =  false;
		_rolePos    =  float3(0,0,0);
		_moveTo     =  _rolePos;
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{		
		_texture = createTextureFromImage("1.jpg");
		_texGround = createTextureFromImage("2.jpg");

		OBJLoader loader;
		loader.load("box.obj");

	}

	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)

		float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

			//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};

		glMatrixMode(GL_MODELVIEW);

		_camera.perspective(60,float(_width)/float(_height),0.1f,1000.0f);

		float3 dir = normalize(_moveTo - _rolePos);//得到移动的方向

		if (length(_moveTo - _rolePos) < 1)
		{
			_rolePos = _moveTo;
		}
		else 
		{
			_rolePos += dir * 1.0f/60.0f;
		}
		_camera.updateLookat(_rolePos);
		//摄像机更新
		_camera.update();

		matrix4 matVP  =  _camera.getMVP();
		glLoadMatrixf(matVP.data());

		glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

		glBindTexture(GL_TEXTURE_2D,_texture);

		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

		glDrawArrays(GL_QUADS,0,24);
		glLoadMatrixf(matVP.data());

		glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);
	}

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_SIZE://窗口大小变化
			{
				if(::IsWindow(hWnd))
				{
					//获取窗口宽高
					RECT rt;
					GetClientRect(_hWnd,&rt);
					int w = rt.right - rt.left;
					int h = rt.bottom - rt.top;
					glViewport(0,0,w,h);//指定视口
					//把屏幕坐标转化成世界坐标
					_camera.setView(w,h);
				}
			}
			break;
		case WM_LBUTTONDOWN:
			{
				_bDownFlag = true;

			}
			break;
		case WM_LBUTTONUP:
			{
				_bDownFlag = true;
				_mouseDown  =   int2(LOWORD(lParam),HIWORD(lParam));

				CELL::Ray   ray     =   _camera.createRayFromScreen(_mouseDown.x,_mouseDown.y);
				float3      orth    =   ray.getOrigin();
				float       tm      =   (orth.y  + 1)/ray.getDirection().y;
				float3      c       =   ray.getOrigin() + abs(tm) * ray.getDirection();
				_moveTo =   c;
			}
			break;
		case WM_MOUSEWHEEL:
			{
				int delta = (short)HIWORD(wParam);//鼠标滚动过的距离(120的整数倍,正的即正向滚动)
				if (delta > 0)
				{
					_camera.setRadius(_camera.getRadius() * 1.2f);
				}
				else
				{
					_camera.setRadius(_camera.getRadius() * 0.8f);
				}
			}
		case WM_MOUSEMOVE:
			{
				if(_bDownFlag)
				{
					int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
					float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
					_mouseDown = mouseCur;
					_camera.rotateY(xOffset * 0.5f);
				}
			}
			break;

			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
					_rolePos.x  -=  1;
					break;
				case VK_RIGHT:
					_rolePos.x  +=  1;
					break;
				case VK_UP:
					_rolePos.z  -=  1;
					break;
				case VK_DOWN:
					_rolePos.z  +=  1;
					break;
				}
			}
			break;
		}
		return __super::events(hWnd,msgId,wParam,lParam);
	}
};

//CALLBACK 标准调用 等价于_stdcall
int CALLBACK WinMain(
					 HINSTANCE hInstance,
					 HINSTANCE hPrevInstance,
					 LPSTR lpCmdLine,
					 int nShowCmd)
{
	SamplerTexture instance;
	instance.main(800,600);

	return 0;
}

3月22日

  • OBJ格式模型的绘制
#pragma once

//加载-绘制
#include "CELLMath.hpp"
#include <vector>
class OBJLoader
{
public:
	struct Face
	{
		unsigned int v1,v2,v3;
		unsigned int n1,n2,n3;//法线索引
		unsigned int t1,t2,t3;
	};
public:

	std::vector<CELL::float3> _vertexs;
	std::vector<CELL::float3> _normals;
	std::vector<CELL::float2> _uvs;
 

public:
	//加载文件
	bool load(const char* fileName)
	{
		FILE* pFile = fopen(fileName,"rt");
		if (pFile == 0)
		{
			return false;
		}

		_vertexs.clear();
		_uvs.clear();
		_normals.clear();
        
		std::vector<Face> arFace;
		while (feof(pFile) == 0)//如果文件没结束
		{
			char szLine[1024];
			fgets(szLine,sizeof(szLine),pFile);//从pFile读数据,最多读sizeof(szLine)到szLine
			//!顶点数据
			if (szLine[0] == 'v' && szLine[1] == ' ')
			{
				CELL::float3 pos;
				sscanf(szLine,"v  %f %f %f",&pos.x,&pos.y,&pos.z);
				_vertexs.push_back(pos);
			}
			else if(szLine[0] == 'v' && szLine[1] == 't')
			{
				CELL::float2 pos;
				sscanf(szLine,"vt  %f %f",&pos.x,&pos.y);
				_uvs.push_back(pos);
			}
			else if(szLine[0] == 'v' && szLine[1] == 'n')
			{
				CELL::float3 pos;
				sscanf(szLine,"vn  %f %f %f",&pos.x,&pos.y,&pos.z);
				_normals.push_back(pos);
			}
			else if(szLine[0] == 'f' && szLine[1] == ' ')
			{
				Face face;
				sscanf(szLine,
					"f  %d%d%d %d%d%d %d%d%d"
					,&face.v1
					,&face.t1
					,&face.n1

					,&face.v2
					,&face.t2
					,&face.n2

					,&face.v3
					,&face.t3
					,&face.n3);

				face.v1 -= 1;
                face.v2 -= 1;
				face.v3 -= 1;

				face.n1 -= 1;
				face.n2 -= 1;
				face.n3 -= 1;

				face.t1 -= 1;
				face.t2 -= 1;
				face.t3 -= 1;
				arFace.push_back(face);
			}
		}

		std::vector<CELL::float3>  vertexs;
		std::vector<CELL::float2>  uvs;
		std::vector<CELL::float3>  normals;
		for (size_t i = 0;i < arFace.size() ;++i)
		{
			Face& f = arFace[i];
			float3 v1 = _vertexs[f.v1];
			float3 v2 = _vertexs[f.v2];
			float3 v3 = _vertexs[f.v3];

			vertexs.push_back(v1);
			vertexs.push_back(v2);
			vertexs.push_back(v3);

			float3 n1 = _normals[f.n1];
			float3 n2 = _normals[f.n2];
			float3 n3 = _normals[f.n3];

			normals.push_back(n1);
			normals.push_back(n2);
			normals.push_back(n3);

			float2 t1 = _uvs[f.t1];
			float2 t2 = _uvs[f.t2];
			float2 t3 = _uvs[f.t3];

			uvs.push_back(t1);
			uvs.push_back(t2);
			uvs.push_back(t3);

		}
		 _normals = normals;
		 _vertexs = vertexs;
		 _uvs     = uvs;

		fclose(pFile);
		return true;
	}

};

class OBJRender: public OBJLoader
{
public:
	void render(CELL::matrix4& mvp)
	{
		glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);//法线
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,    0,   &_vertexs.front());
		glNormalPointer(GL_FLOAT,      0,   &_normals.front());
        glTexCoordPointer(2,GL_FLOAT,  0,&_uvs[0]);
	
		glDrawArrays(GL_TRIANGLES,0,_vertexs.size());
	}
};
#include <windows.h>
#include <tchar.h>

#include <math.h>
#include "FreeImage.h"

#include "CELLMath.hpp"
#include "OpenGLWindow.h"
#include "Camera3rd.h"
#include <vector>
#include "OBJLoader.hpp"
using namespace CELL;

//创建win32窗口

struct Vertex 
{ 
	float x,y,z;//每一个占1个字节
	float u,v;
};

class SamplerTexture:public OpenGLWindow
{
	//OpenGL里的纹理对应的是数字
	GLuint _texture;//纹理句柄;数字,无符号int

	GLuint _texGround;

	Camera3rd _camera;
	int2 _mouseDown;
	bool _bDownFlag;//鼠标按下的标志

	float3 _rolePos;
	float3 _moveTo;

	OBJRender _loader;
public:
	SamplerTexture() 
	{
		_bDownFlag  =  false;
		_rolePos    =  float3(0,0,0);
		_moveTo     =  _rolePos;
	}
	/*使用FreeImage加载图片*/
	unsigned createTextureFromImage(const char* fileName)//返回值是纹理的ID
	{
		//获取图片格式
		FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName,0);
		if(fifmt == FIF_UNKNOWN)
		{
			return 0;
		}

		//加载图片
		FIBITMAP  *dib = FreeImage_Load(fifmt,fileName,0);//调此函数才真正的将图片读入内存中,返回一个指针
		FREE_IMAGE_COLOR_TYPE type  =  FreeImage_GetColorType(dib);

		//获取数据指针
		FIBITMAP* temp  =  dib;
		dib = FreeImage_ConvertTo32Bits(dib);
		FreeImage_Unload(temp);//释放原来对象

		BYTE*  pixels = (BYTE*)FreeImage_GetBits(dib);//获取dib的内容,若图片是压缩的内容是解压完成后的
		int width = FreeImage_GetWidth(dib);
		int height = FreeImage_GetHeight(dib);

		//默认情况下加载来的数据是bgra
		for(int i = 0;i<width * height * 4 ;i += 4)
		{
			BYTE temp      = pixels[i];
			pixels[i]      = pixels[i + 2];
			pixels[i + 2]  =temp;
		}

		unsigned res = createTexture(width,height,pixels);
		FreeImage_Unload(dib);
		return res;

	}

	unsigned createTexture(int w,int h,const void* data)
	{
		unsigned texId;
		glGenTextures(1,&texId);//产生纹理 
		glBindTexture(GL_TEXTURE_2D,texId);//绑定纹理
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);//分配纹理的显存

		return texId;
	}
	virtual void onInitGL()
	{		
		_texture = createTextureFromImage("1.jpg");
		_texGround = createTextureFromImage("2.jpg");

		_loader.load("box.obj");

	}
	//在此实现绘制
	virtual void render()
	{
#define M_PI (3.14159265358979323846)

		float  size = 100;

		Vertex cubeVertices[] =
		{
			{-1.0f,-1.0f,1.0f,0.3f,0.3f},
			{ 1.0f,-1.0f,1.0f,0.5f,0.3f},
			{ 1.0f, 1.0f,1.0f,0.5f,0.8f},
			{-1.0f, 1.0f,1.0f,0.3f,0.8f},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f, 1.0f,-1.0f,1,0},
			{ 1.0f, 1.0f,-1.0f,1,1},
			{ 1.0f,-1.0f,-1.0f,0,1},

			{-1.0f, 1.0f,-1.0f,0,0},
			{-1.0f, 1.0f, 1.0f,1,0},
			{ 1.0f, 1.0f, 1.0f,1,1},
			{ 1.0f, 1.0f,-1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{ 1.0f,-1.0f,-1.0f,1,0},
			{ 1.0f,-1.0f, 1.0f,1,1},
			{-1.0f,-1.0f, 1.0f,0,1},

			{1.0f,-1.0f,-1.0f,0,0},
			{1.0f, 1.0f,-1.0f,1,0},
			{1.0f, 1.0f, 1.0f,1,1},
			{1.0f,-1.0f, 1.0f,0,1},

			{-1.0f,-1.0f,-1.0f,0,0},
			{-1.0f,-1.0f, 1.0f,1,0},
			{-1.0f, 1.0f, 1.0f,1,1},
			{-1.0f, 1.0f,-1.0f,0,1},

			//!地面数据

			{-size, -1,-size,0,0},
			{-size, -1, size,100,0},
			{ size, -1, size,100,100},
			{ size, -1,-size,0,100},
		};


        //! 指定以下的操作针对投影矩阵
		glMatrixMode(GL_MODELVIEW);

		_camera.perspective(60,float(_width)/float(_height),0.1f,1000.0f);

		float3 dir = normalize(_moveTo - _rolePos);//得到移动的方向

		if (length(_moveTo - _rolePos) < 1)
		{
			_rolePos = _moveTo;
		}
		else 
		{
			_rolePos += dir * (10.0f/60.0f);
		}
		_camera.updateLookat(_rolePos);
		//摄像机更新
		_camera.update();


		matrix4 matVP  =  _camera.getMVP();
		glLoadMatrixf(matVP.data());

		glTranslatef(_rolePos.x,_rolePos.y,_rolePos.z);

		glBindTexture(GL_TEXTURE_2D,_texture);

		glEnable(GL_DEPTH_TEST);//深度测试
		glEnable(GL_TEXTURE_2D);

		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		glVertexPointer(3,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].x);
		glTexCoordPointer(2,GL_FLOAT,sizeof(Vertex),&cubeVertices[0].u);

        
		glDrawArrays(GL_QUADS,0,24);
		glLoadMatrixf(matVP.data());

		glBindTexture(GL_TEXTURE_2D,_texGround);
		glDrawArrays(GL_QUADS,24,4);

		//绘制模型
		_loader.render(matVP);

    }

	virtual LRESULT events(HWND hWnd,UINT msgId,WPARAM wParam,LPARAM lParam)
	{
		switch(msgId)
		{
		case WM_SIZE://窗口大小变化
			{
				if(::IsWindow(hWnd))
				{
					//获取窗口宽高
					RECT rt;
					GetClientRect(_hWnd,&rt);
					int w = rt.right - rt.left;
					int h = rt.bottom - rt.top;
					glViewport(0,0,w,h);//指定视口
					//把屏幕坐标转化成世界坐标
					_camera.setView(w,h);
				}
			}
			break;
		case WM_LBUTTONDOWN:
			{
				_bDownFlag = true;
				_mouseDown  =   int2(LOWORD(lParam),HIWORD(lParam));

				CELL::Ray   ray     =   _camera.createRayFromScreen(_mouseDown.x,_mouseDown.y);
				float3      orth    =   ray.getOrigin();
				float       tm      =   (orth.y  + 1)/ray.getDirection().y;
				float3      c       =   ray.getOrigin() + abs(tm) * ray.getDirection();
				_moveTo =   c;
			}
			break;
		case WM_LBUTTONUP:
			{
				_bDownFlag = false;	
			}
			break; 

		case WM_MOUSEWHEEL:
			{
				int delta = (short)HIWORD(wParam);//鼠标滚动过的距离(120的整数倍,正的即正向滚动)
				if (delta > 0)
				{
					_camera.setRadius(_camera.getRadius() * 1.2f);
				}
				else
				{
					_camera.setRadius(_camera.getRadius() * 0.8f);
				}
			}
		case WM_MOUSEMOVE:
			{
				if(_bDownFlag)
				{
					int2 mouseCur = int2(LOWORD(lParam),HIWORD(lParam));
					float  xOffset  = mouseCur.x - _mouseDown.x;//当前位置-鼠标按下位置
					_mouseDown = mouseCur;
					_camera.rotateY(xOffset * 0.5f);
				}
			}
			break;
			//响应键盘
		case WM_KEYDOWN:
			{
				switch(wParam)//键
				{
				case VK_LEFT:
					_rolePos.x  -=  0.1;
					break;
				case VK_RIGHT:
					_rolePos.x  +=  0.1;
					break;
				case VK_UP:
					_rolePos.z  -=  0.1;
					break;
				case VK_DOWN:
					_rolePos.z  +=  0.1;
					break;
				}
			}
			break;
		
        }
        return  __super::events(hWnd,msgId,wParam,lParam);
    }
};

int __stdcall WinMain( 
                      HINSTANCE hInstance, 
                      HINSTANCE hPrevInstance, 
                      LPSTR lpCmdLine, 
                      int nShowCmd
                      )
{

    SamplerTexture    instance;
    instance.main(800,600);


    return  0;
}

3月25日

  • OBJ模型材质(纹理的加载)
#pragma once

#include    "CELLMath.hpp"
#include    <vector>
class   OBJLoader
{
public:

    struct  Face
    {
        unsigned int  v1,v2,v3;
        unsigned int  n1,n2,n3;
        unsigned int  t1,t2,t3;
    };

    struct  Material
    {
        float3  ambient;
        float3  diffuse;
        float3  specal;
        char    szTex[128];
        GLuint  texId;
    };

public:

    std::vector<CELL::float3>   _vertexs;
    std::vector<CELL::float3>   _normals;
    std::vector<CELL::float2>   _uvs;
    Material                    _material;
public:

    OBJLoader()
    {
        memset(&_material,0,sizeof(_material));

    }

    /**
    *   加载文件
    */

    virtual bool    load(const char* fileName)
    {
        FILE*   pFile   =   fopen(fileName,"rt");
        if (pFile == 0)
        {
            return  false;
        }

        _vertexs.clear();
        _uvs.clear();
        _normals.clear();
        

        std::vector<Face>   arFace;
        while (feof(pFile) == 0)
        {
            char    szLine[1024];
            fgets(szLine,sizeof(szLine),pFile);

            if (strncmp(szLine,"mtllib",6) == 0)
            {
                char    matFile[128];
                sscanf(szLine,"mtllib %s",matFile);
                parseMaterial(matFile);
            }
            //! 顶点数据
            else if (szLine[0] == 'v' && szLine[1] == ' ')
            {
                CELL::float3    pos;
                sscanf(szLine,"v  %f %f %f",&pos.x,&pos.y,&pos.z);
                _vertexs.push_back(pos);
            }
            else if(szLine[0] == 'v' && szLine[1] == 't')
            {
                CELL::float2    pos;
                sscanf(szLine,"vt  %f %f",&pos.x,&pos.y);
                _uvs.push_back(pos);
            }
            else if(szLine[0] == 'v' && szLine[1] == 'n')
            {
                CELL::float3    pos;
                sscanf(szLine,"vn  %f %f %f",&pos.x,&pos.y,&pos.z);
                _normals.push_back(pos);
            }
            else if(szLine[0] == 'f' && szLine[1] == ' ')
            {
                Face    face;
                sscanf(szLine,
                    "f %d/%d/%d %d/%d/%d %d/%d/%d"
                    ,&face.v1
                    ,&face.t1
                    ,&face.n1
                    ,&face.v2
                    ,&face.t2
                    ,&face.n2 
                    ,&face.v3
                    ,&face.t3
                    ,&face.n3);

                face.v1 -=  1;
                face.v2 -=  1;
                face.v3 -=  1;
                face.n1 -=  1;
                face.n2 -=  1;
                face.n3 -=  1;
                face.t1 -=  1;
                face.t2 -=  1;
                face.t3 -=  1;
                arFace.push_back(face);
            }
        }

        std::vector<CELL::float3>   vertexs;
        std::vector<CELL::float2>   uvs;
        std::vector<CELL::float3>   normals;
        for (size_t i = 0 ;i < arFace.size() ; ++ i)
        {
            Face&   f   =   arFace[i];
            float3  v1   =   _vertexs[f.v1];
            float3  v2   =   _vertexs[f.v2];
            float3  v3   =   _vertexs[f.v3];

            vertexs.push_back(v1);
            vertexs.push_back(v2);
            vertexs.push_back(v3);

            float3  n1   =   _normals[f.n1];
            float3  n2   =   _normals[f.n2];
            float3  n3   =   _normals[f.n3];

            normals.push_back(n1);
            normals.push_back(n2);
            normals.push_back(n3);

            float2  t1   =   _uvs[f.t1];
            float2  t2   =   _uvs[f.t2];
            float2  t3   =   _uvs[f.t3];

            uvs.push_back(t1);
            uvs.push_back(t2);
            uvs.push_back(t3);
        }

        _normals    =   normals;
        _vertexs    =   vertexs;
        _uvs        =   uvs;
        fclose(pFile);
        return  true;
    }


    virtual bool    parseMaterial(const char* fileName)
    {
        FILE*   pFile   =   fopen(fileName,"rt");
        if (pFile == 0)
        {
            return  false;
        }

        while (feof(pFile) == 0)
        {
            char    szLine[1024];
            fgets(szLine,sizeof(szLine),pFile);

            if (strncmp(szLine,"Ka",2) == 0)
            {
                sscanf(szLine,"Ka  %f %f %f"
                    ,&_material.ambient.x
                    ,&_material.ambient.y
                    ,&_material.ambient.z);
            }
            else if (strncmp(szLine,"Kd",2) == 0)
            {
                sscanf(szLine,"Kd  %f %f %f"
                    ,&_material.diffuse.x
                    ,&_material.diffuse.y
                    ,&_material.diffuse.z);
            }
            else if (strncmp(szLine,"Ks",2) == 0)
            {
                sscanf(szLine,"Ks  %f %f %f"
                    ,&_material.specal.x
                    ,&_material.specal.y
                    ,&_material.specal.z);
            }
            else if (strncmp(szLine,"map_Kd",6) == 0)
            {
                sscanf(szLine,"map_Kd %s",_material.szTex);
            }
        }
        fclose(pFile);

        return  true;

    }

};


class   OBJRender :public OBJLoader
{
public:

        /**
    *   使用FreeImage加载图片
    */
    unsigned    createTextureFromImage(const char* fileName)
    {
        //1 获取图片格式
        FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
        if (fifmt == FIF_UNKNOWN)
        {
            return  0;
        }
        //2 加载图片
        FIBITMAP    *dib = FreeImage_Load(fifmt, fileName,0);
     
        FREE_IMAGE_COLOR_TYPE type    =   FreeImage_GetColorType(dib);
      
        //! 获取数据指针
        FIBITMAP*   temp    =   dib;
        dib =   FreeImage_ConvertTo32Bits(dib);
                FreeImage_Unload(temp);

        BYTE*   pixels =   (BYTE*)FreeImage_GetBits(dib);
        int     width   =   FreeImage_GetWidth(dib);
        int     height  =   FreeImage_GetHeight(dib);

        for (int i = 0 ;i < width * height * 4 ; i+=4 )
        {
            BYTE temp       =   pixels[i];
            pixels[i]       =   pixels[i + 2];
            pixels[i + 2]   =   temp;
        }

        unsigned    res =   createTexture(width,height,pixels);
        FreeImage_Unload(dib);
        return      res;
    }

    unsigned    createTexture(int w,int h,const void* data)
    {
        unsigned    texId;
        glGenTextures(1,&texId);
        glBindTexture(GL_TEXTURE_2D,texId);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,data);

        return  texId;
    }

    bool    load(const char* fileName)
    {
        bool    res =   OBJLoader::load(fileName);
        if (res && strlen(_material.szTex) > 0)
        {
            _material.texId =   createTextureFromImage(_material.szTex);
        }

        return  res;
    }
    void    render(CELL::matrix4& mvp)
    {
        if (_material.texId != 0)
        {
            glBindTexture(GL_TEXTURE_2D,_material.texId);
        }


        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_NORMAL_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glVertexPointer(3,GL_FLOAT,         0,     &_vertexs.front());
        glNormalPointer(GL_FLOAT,           0,     &_normals.front());
        glTexCoordPointer(2,GL_FLOAT,       0,     &_uvs[0]);

        glDrawArrays(GL_TRIANGLES,0,_vertexs.size());

    }
};

暑期计划

1、看视频,学习研究生的核心能力
2、了解Unity、学习CryEngine

目前工作

搜集CryEngine新手入门资料:
电子书:
1、CryENGINE 3CookBook中文发布版:这份资料更像是一个总结,理论讲解和实践相结合
2、CryENGINE3游戏开发新手指南(中文版),刘强汉化:这本参考书介绍的更加系统化,侧重点在实践例子上
视频教程:
3、Cryengine 5 国内首套零基础入门视频课程(网址:https://edu.manew.com/goods/show/211?targetId=341&preview=0)

每日学习情况

  • 8月19日

CryEngine5入门视频课的8 9 10 11小课,主要学习塑造地形 绘制地表 放置静态模型。

  • 8月20日

看了Cryengine5入门视频课的12 13 14小课,学习关卡管理 植被管理器里,因为目前没有安装好素材包,无法练习,等安装好素材包以后,再跟着视频在CryEngine上练习。

  • 8月23日

这两天刚把素材包装好,今天练习放置模型,学习植被管理器,去做关卡管理、地表绘制,做一个完整的地形贴图出来。

  • 8月24日

熟悉道路及河流工具,目前是贴图可以做出来,不过不太美观,细节方面需要提升。

  • 8月25日

学习基础打光和放置粒子特效,主要放在熟悉软件的使用上,对各个功能熟悉。

  • 8月26日

主要学习天气系统(TOD),使用标签设置光的强度阳光的角度,还有对雾进行一些操作,并设置风的速度,放置云以及云的运动速度。

  • 8月30日

学习体积雾的相关设置,天气系统的HDR相关设置,并放置其他Entity实体,比如雨、雪、篱笆路障、绳索等。

目前贴图 1
目前贴图 2




























  • 9月3日

学习音效系统,Audio Trigger Spot(音频触发点)-声音有指向性,Audio Area Ambience-环境音。

  • 9月6日

学习Flowgraph基本逻辑及事件触发,主要是给场景加一些互动的功能,例如通过发动机控制灯的开关。
逻辑图如下图所示:

FlowGraph逻辑图


















  • 9月7日

完善昨天的逻辑和事件触发,继续构建稍微复杂一点的逻辑:

场景互动


















结果:













  • 9月8日

学习关卡设计工具,主要应用在关卡里制作空气墙;学习TrackView过场动画系统;学习计算机图形学第一节;

  • 9月9日

学习计算机图形学中的一些重要概念:色彩视觉、图像和像素、三角网格模型、法向量、三角网格的简单绘制、光照模型、光线传播的能量方程、光的度量方法、Phong光照模型等。

  • 9月10日

<1>学习从水经微图上下载导出地图,从GeoServer上发布地图;目前的进展是已经可以从微图上导出矢量数据的地图和.tif格式的碎片,GeoServer上可以发布出去地图,但是预览不了,只是空白页面;新建的s矢量数据源和栅格数据源都存在这个问题。

发布的地图无法预览



















<2>学习计算机图形学,明暗处理,视点变换和视点方向。

  • 9月14日

学习计算机图形学,投影模式:正交投影、透视投影;并补充预备知识:球面坐标,立体角,投影面积,光能,光通量,辉度,发光强度,光亮度以及他们所涉及到的公式;双向反射分布函数(BRDF)的定义和性质,可逆性、能量守恒性质、基于BRDF的渲染方程;BRDF的数值模型(经验模型、基于物理的模型、数据表达的模型);

  • 9月15日

1、了解了下CryEngine AR的项目,不过对于我要完成的部分,现在思路不是很清晰,而且搜集到的资料很少,还需要继续找资料。
2、学习计算机图形学,主要是学习基于物理的模型(菲涅尔项、Cook-Torrance模型和一些其他的物理模型,如Ward模型、Oren-Nayar模型、Poulin-Fournier模型、波动光学相关模型),数据表达的模型,并对三类模型进行定性分析,并对BRDF进行了度量和评价。

  • 9月16日

学习计算机图形学,今天主要学习光线跟踪算法、追踪的特征与光线求交(光线的表示、光线与平面求交、光线与三角形求交、光线与多边形求交、光线与球面求交、光线与长方体求交),判断点是否在多边形内部的交点检测算法、最快的点包含判别算法(弧长法)。

  • 9月17日

学习前向光线跟踪、光线跟踪加速;包围体(平行于坐标轴的包围盒AABB、非平行于坐标轴的包围盒OBB、包围球)、层次包围体HBV,均匀格点;相交检测;

  • 9月22日

1、实现将.obj文件从磁盘存入内存缓冲流,并再存回磁盘验证。 2、八叉树(构建、性质、空间八叉树剖分技术);光线跟踪过程;空间二分树(BSP)(Polygon-aligned BSP树和Axis-aligned BSP树);Axis-aligned BSP树构建;参数曲线及曲面的基本概念;Bezier曲线(概念、性质)。

  • 9月23日

计算机图形学,de Casteljau算法,Bezier曲线的递推计算公式,几何连续性,升阶降阶,Bezier曲面,矩形域Bezier曲面,矩阵域Bezier曲面性质,三角域Bezier曲面(定义、性质)。