平时我们看到电脑艺术笔写毛笔字,非常爽 也有朋友经常在群里炫耀自己毛笔字.如果自己能开发一款艺术笔软件那是多好啊,于是开始计划搜集资料 ,然后向众群求教,结果是数学要好,需要算法,并推荐了文章.结果文章打不开,我也没有拜读.只好开始自己动手啦.
既然学OPENGL 编程 那一定能实现,
基本思路,艺术笔的特点是 要有墨迹感 且墨水有收缩感 这个难度 其他写字很容易实现.于是想到纹理和混色 透明技术 ,首先加载纹理 ,用纹理来仿照毛笔字的粗糙度 用粒子来模拟散落的墨点.废话少说,动手写代码:
// wsqView.h : interface of the CWsqView class
//
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_WSQVIEW_H__CF299264_8764_4342_9C5A_F0F9BA26FA75__INCLUDED_)
#define AFX_WSQVIEW_H__CF299264_8764_4342_9C5A_F0F9BA26FA75__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "gl\gl.h" //包含gl.h库
#include "gl\glu.h" //包含glu.h库
#include "gl\glaux.h" //包含OpenGL实用库
#pragma comment( lib, "opengl32.lib") //链接OpenGL库
#pragma comment( lib, "glu32.lib")
#pragma comment( lib, "glaux.lib")
struct ColorPoint //定义结构体
{
float x,y;//坐标
float size;
float color[3]; //颜色
int life;
};
class CWsqView : public CView
{
protected: // create from serialization only
CWsqView();
DECLARE_DYNCREATE(CWsqView)
// Attributes
public:
CWsqDoc* GetDocument();
// Operations
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWsqView)
//}}AFX_VIRTUAL
public:
void LoadTextures(); //读入纹理
void DrawScene(); //绘制场景
// void DrawOtherScene();
//初始化Opengl相关
BOOL CreateViewGLContext(HDC hDC); //创建绘制环境并使之成为当前绘制环境
BOOL SetWindowPixelFormat(HDC hDC); //像素格式
HWND m_hWnd; //窗口句柄
HDC m_hDC; //设备描述表
HGLRC m_hGLContext; //图形操作描述表
int m_GLPixelIndex;
GLuint m_texture[10]; //纹理10个
int m_iWindowWidth,m_iWindowHeight; //窗口大小
bool m_bKey[256];
bool m_LeftButtonDown;
// virtual BOOL OnNewDocument();
CPoint m_MousePos; //鼠标...
// DWORD m_iFrame; //帧
int m_iSimStartPoint; //模拟起始点
int m_iDrawStartPoint; //开始画的点
int m_iPointNum; //点的数量
float m_fPointSize; //点的大小
float m_Color[3]; //点的颜色
// bool m_bSpread;
bool m_bBrush;
ColorPoint m_ColorPoint[10000];
int m_ImageWidth;
int m_ImageHeight;
// Implementation
public:
virtual ~CWsqView();
void Spread();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// Generated message map functions
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
//{{AFX_MSG(CWsqView)
// NOTE - the ClassWizard will add and remove member functions here.
// DO NOT EDIT what you see in these blocks of generated code !
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
#ifndef _DEBUG // debug version in wsqView.cpp
inline CWsqDoc* CWsqView::GetDocument()
{ return (CWsqDoc*)m_pDocument; }
#endif
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_WSQVIEW_H__CF299264_8764_4342_9C5A_F0F9BA26FA75__INCLUDED_)
=============================================================
// wsqView.cpp : implementation of the CWsqView class
//
#include "stdafx.h"
#include "wsq.h"
#include "wsqDoc.h"
#include "wsqView.h"
#include <MATH.H>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CWsqView
CView* g_pView;
bool resetView = false;
IMPLEMENT_DYNCREATE(CWsqView, CView)
//消息隐射
BEGIN_MESSAGE_MAP(CWsqView, CView)
//{{AFX_MSG_MAP(CWsqView)
//}}AFX_MSG_MAP
// Standard printing commands
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
// ON_COMMAND(ID_FILE_NEW, CView::OnFileNew)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWsqView construction/destruction
BYTE tempdata[1024*1024*3]; //零时数据大小
CWsqView::CWsqView()
{
// TODO: add construction code here
m_LeftButtonDown = false; //初始化
for(int i=0;i<256;i++)
{
m_bKey[i]=false;
}
m_iPointNum = 0;
m_iSimStartPoint = 0;
m_iDrawStartPoint = 0;
m_fPointSize = 0;
m_Color[0]=1.0;
m_Color[1]=1.0;
m_Color[2]=1.0;
int life = 0;
m_bBrush = true;
}
CWsqView::~CWsqView()
{
}
BOOL CWsqView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style|=WS_CLIPSIBLINGS|WS_CLIPCHILDREN; //指定窗口风格
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CWsqView drawing
void CWsqView::OnDraw(CDC* pDC) //绘图函数
{
CWsqDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if(resetView)
{
m_iSimStartPoint=m_iDrawStartPoint=m_iPointNum=0;//初始化
resetView = false;
}
// TODO: add draw code for native data here
if(pDoc->m_bImageChanged) //使得可以新建一个画图区
{
glBindTexture(GL_TEXTURE_2D,m_texture[1]);
m_ImageWidth=pDoc->m_ImageWidth;
m_ImageHeight=pDoc->m_ImageHeight;//纹理贴图
// if(m_bKey[VK_TAB])
// pDoc->m_bImageChanged = true;
glTexSubImage2D(GL_TEXTURE_2D, //子纹理
0,
512-m_ImageWidth/2,
512-m_ImageHeight/2,
m_ImageWidth,
m_ImageHeight,
GL_RGB,
GL_UNSIGNED_BYTE,
pDoc->m_pImage);//定义一个存在的二维纹理图像的一部分,但不能定义新的纹理
pDoc->m_bImageChanged = false;
// if(m_bKey[VK_TAB])
// pDoc->m_bImageChanged = true;
}
DrawScene();
// if(m_bKey[VK_TAB])
// pDoc->m_bImageChanged = true;
// Spread();
SetTimer(0,30,NULL); //定时30毫秒
SwapBuffers(m_hDC); //切换缓冲区 启用用双缓冲
}
/////////////////////////////////////////////////////////////////////////////
// CWsqView printing
//打印
BOOL CWsqView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
//重新打印
void CWsqView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CWsqView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CWsqView diagnostics
#ifdef _DEBUG
void CWsqView::AssertValid() const
{
CView::AssertValid();
}
void CWsqView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CWsqDoc* CWsqView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWsqDoc)));
return (CWsqDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CWsqView message handlers
BOOL CWsqView::SetWindowPixelFormat(HDC hDC)
{
PIXELFORMATDESCRIPTOR pixelDesc; //像素图结构体
pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); //说明该数据结构的长度
pixelDesc.nVersion = 1; //说明该数据结构的版本
pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER | PFD_STEREO_DONTCARE; //指定像素缓存的属性:支持window,支持OpenGL,像素存为双缓存、立方体结构。
pixelDesc.iPixelType = PFD_TYPE_RGBA; // 指定RGBA模式
pixelDesc.cColorBits = 32; //说明颜色缓存中颜色位平面的个数
pixelDesc.cRedBits = 0;
pixelDesc.cRedShift = 0;
pixelDesc.cGreenBits = 0;
pixelDesc.cGreenShift = 0;
pixelDesc.cBlueBits = 0;
pixelDesc.cBlueShift = 0;
pixelDesc.cAlphaBits = 0;
pixelDesc.cAlphaShift = 0;
pixelDesc.cAccumBits = 64; //说明累积缓存位平面的个数
pixelDesc.cAccumRedBits = 0;
pixelDesc.cAccumGreenBits = 0;
pixelDesc.cAccumBlueBits = 0;
pixelDesc.cAccumAlphaBits = 0;
pixelDesc.cDepthBits = 32; //说明模板缓存的位数
pixelDesc.cStencilBits = 8; //说明模板缓存的位数
pixelDesc.cAuxBuffers = 0; //说明辅助缓存的个数
pixelDesc.iLayerType = PFD_MAIN_PLANE;
pixelDesc.bReserved = 0;
pixelDesc.dwLayerMask = 0;
pixelDesc.dwVisibleMask = 0;
pixelDesc.dwDamageMask = 0;
m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc);
if(m_GLPixelIndex == 0) // Choose default
{
m_GLPixelIndex = 1;
if(DescribePixelFormat(hDC,m_GLPixelIndex,
sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0)
return FALSE;
}
if(!SetPixelFormat(hDC,m_GLPixelIndex,&pixelDesc))
return FALSE;
return TRUE;
}
BOOL CWsqView::CreateViewGLContext(HDC hDC)
{
m_hGLContext = wglCreateContext(hDC); //创建RC
if(m_hGLContext==NULL) //创建失败
return FALSE;
if(wglMakeCurrent(hDC,m_hGLContext)==FALSE) //选为当前RC失败
return FALSE;
return TRUE;
}
void CWsqView::LoadTextures() //载入纹理
{
AUX_RGBImageRec *TextureImage; //颜色对象
TextureImage = auxDIBImageLoad(_T("Data/tree.bmp")); //载入bmp图,并转换为纹理
glGenTextures(1,&m_texture[0]); // 创建一个新纹理
glBindTexture(GL_TEXTURE_2D,m_texture[0]); //关联一个纹理
//设定纹理参数
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); // 创建使用线性Mipmap过滤器过滤得纹理,即使用线性插值计算两个图像中的每个图像的纹素值,然后在两个图像间进行线性插值
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //放大、缩小纹理滤波
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); //使用重复贴图
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,TextureImage->sizeX,TextureImage->sizeY,GL_RGB,GL_UNSIGNED_BYTE,TextureImage->data);//创建二维多重映射
//glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);
free(TextureImage->data); //释放数据
free(TextureImage); //释放纹理对象
TextureImage = auxDIBImageLoad(_T("Data/Terrain.bmp")); //载入bmp图,并转换为纹理
glGenTextures(1,&m_texture[1]);// 创建纹理
glBindTexture(GL_TEXTURE_2D,m_texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // 创建使用临近过滤器过滤得纹理,选择最接近像素中心的纹素进行放大或缩小
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);//不使用重复贴图
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,1024,1024,GL_RGB,GL_UNSIGNED_BYTE,tempdata); //定义分辨率逐渐减小到2*2的多重图像,并将原图缩放到最接近2的幂次方的尺寸上
// glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);
free(TextureImage->data);
free(TextureImage);
TextureImage = auxDIBImageLoad(_T("Data/grass1.bmp")); //载入bmp图,并转换为纹理
glGenTextures(1,&m_texture[2]); // 创建纹理
glBindTexture(GL_TEXTURE_2D,m_texture[2]);
free(TextureImage->data);
free(TextureImage);
TextureImage = auxDIBImageLoad(_T("Data/Butterfly3.bmp")); //载入bmp图,并转换为纹理
glGenTextures(1,&m_texture[3]);// 创建纹理
glBindTexture(GL_TEXTURE_2D,m_texture[3]);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,1024,1024,GL_RGB,GL_UNSIGNED_BYTE,tempdata); //定义分辨率逐渐减小到2*2的多重图像,并将原图缩放到最接近2的幂次方的尺寸上
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);
free(TextureImage->data);
free(TextureImage);
/* int Status=FALSE; // Status Indicator
AUX_RGBImageRec *TextureImage[4]; // Create Storage Space For The Textures
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
if (TextureImage[0]=LoadBMP("Data/Particle.bmp")) // Load Particle Texture
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[0]); // Create One Texture
glBindTexture(GL_TEXTURE_2D, texture[0]);
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, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
}
if (TextureImage[1]=LoadBMP("Data/grass1.bmp")) // Load Particle Texture
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[1]); // Create One Texture
glBindTexture(GL_TEXTURE_2D, texture[1]);
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, 3, 1024, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, tempdata);
}
if (TextureImage[2]=LoadBMP("Data/Terrain.bmp")) // Load Particle Texture
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[2]); // Create One Texture
glBindTexture(GL_TEXTURE_2D, texture[2]);
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, 3, TextureImage[2]->sizeX, TextureImage[2]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[2]->data);
}
if (TextureImage[3]=LoadBMP("Data/tree.bmp")) // Load Particle Texture
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[3]); // Create One Texture
glBindTexture(GL_TEXTURE_2D, texture[3]);
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, 3, TextureImage[3]->sizeX, TextureImage[3]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[3]->data);
}
if (TextureImage[0]) // If Texture Exists
{
if (TextureImage[0]->data) // If Texture Image Exists
{
free(TextureImage[0]->data); // Free The Texture Image Memory
}
free(TextureImage[0]); // Free The Image Structure
}
if (TextureImage[1]) // If Texture Exists
{
if (TextureImage[1]->data) // If Texture Image Exists
{
free(TextureImage[1]->data); // Free The Texture Image Memory
}
free(TextureImage[1]); // Free The Image Structure
}
if (TextureImage[2]) // If Texture Exists
{
if (TextureImage[2]->data) // If Texture Image Exists
{
free(TextureImage[2]->data); // Free The Texture Image Memory
}
free(TextureImage[2]); // Free The Image Structure
}
if (TextureImage[3]) // If Texture Exists
{
if (TextureImage[3]->data) // If Texture Image Exists
{
free(TextureImage[3]->data); // Free The Texture Image Memory
}
free(TextureImage[3]); // Free The Image Structure
}
return Status; */ // Return The Status
}
void CWsqView::DrawScene()//绘制场景
{
int pNum;
glClearColor(0,0,0,0); //设置背景颜色
// if(m_bKey[VK_TAB])
// glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
glLoadIdentity(); //重置当前的模型观察矩阵
glEnable(GL_TEXTURE_2D); //启用二维纹理映射
glBindTexture(GL_TEXTURE_2D,m_texture[1]); //创建纹理
glColor3f(1,1,1); //设置颜色为白色
glBegin(GL_QUADS); //绘制四边形
glTexCoord2f(0,0); //设定当前纹理坐标
glVertex2f(-512,-512); //指定顶点,即纹理坐标(0,0)被映射到物体顶点(-512,-512)上
// glColor3f(1.0,0.0,0.0);
glTexCoord2f(0,1); //设定当前纹理坐标
glVertex2f(-512,512); //指定顶点
// glColor3f(0.0,1.0,0.0);
glTexCoord2f(1,1);
glVertex2f(512,512);
// glColor3f(0.0,0.0,1.0);
glTexCoord2f(1,0);
glVertex2f(512,-512);
// glColor3f(1.0,0.0,0.0);
glEnd(); //关闭纹理映射
glEnable(GL_BLEND); //启用混色效果
if(m_bBrush)
// glBlendFunc(GL_ONE,GL_ONE);// 当画刷为真时具体混色方案,第一个参数是源融合因子,后一个是目标融合因子
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
else
glBlendFunc(GL_SRC_COLOR,GL_ONE_MINUS_SRC_COLOR); //当画刷不为真时,采用另一种混色方案
glBindTexture(GL_TEXTURE_2D,m_texture[0]);
glBegin(GL_TRIANGLES);
// glBegin(GL_QUADS);
for(int i=m_iDrawStartPoint;i<m_iSimStartPoint;i++)
{
pNum = i%10000;
glColor3fv(m_ColorPoint[pNum].color);
glTexCoord2f(0,0);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
glTexCoord2f(0,0.5);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
glTexCoord2f(0.5,0.5);
glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
// glTexCoord2f(1,0);
// glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
}
glEnd();
glBindTexture(GL_TEXTURE_2D,m_texture[1]);
glCopyTexSubImage2D(GL_TEXTURE_2D,0,512-m_iWindowWidth/2,512-m_iWindowHeight/2,0,0,m_iWindowWidth,m_iWindowHeight);
m_iDrawStartPoint=m_iSimStartPoint;
glBindTexture(GL_TEXTURE_2D,m_texture[0]);
// glBegin(GL_QUADS);
glBegin(GL_TRIANGLES);
for(int i=m_iSimStartPoint;i<m_iPointNum;i++)
{
pNum = i%10000;
glColor3fv(m_ColorPoint[pNum].color);
//glTexCoord2f(0,0);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
//glTexCoord2f(0,0.5);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
//glTexCoord2f(0.5,0.5);
glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
// glTexCoord2f(1,0);
// glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
}
glEnd();
glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
if(m_bKey[VK_TAB])
glColor3f(0.9,0.9,0.8);
else
glColor3f(1.0,1.0,1.0);
// Spread();
glBegin(GL_QUADS);
glVertex2f(-m_iWindowWidth/2,-m_iWindowHeight/2);
glVertex2f(m_iWindowWidth/2,-m_iWindowHeight/2);
glVertex2f(m_iWindowWidth/2,m_iWindowHeight/2);
glVertex2f(-m_iWindowWidth/2,m_iWindowHeight/2);
glEnd();
glDisable(GL_BLEND);
}
/*void CWsqView::DrawOtherScene() 其他场景绘制
{
int pNum;
glClearColor(0,0,0,0); //设置背景颜色
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
glLoadIdentity(); //重置当前的模型观察矩阵
glEnable(GL_TEXTURE_2D); //启用二维纹理映射
glBindTexture(GL_TEXTURE_2D,m_texture[1]); //创建纹理
glColor3f(1,1,1); //设置颜色为白色
glBegin(GL_QUADS); //绘制四边形
glTexCoord2f(0,0); //设定当前纹理坐标
glVertex2f(-512,-512); //指定顶点,即纹理坐标(0,0)被映射到物体顶点(-512,-512)上
// glColor3f(1.0,0.0,0.0);
glTexCoord2f(0,1); //设定当前纹理坐标
glVertex2f(-512,512); //指定顶点
// glColor3f(0.0,1.0,0.0);
glTexCoord2f(1,1);
glVertex2f(512,512);
// glColor3f(0.0,0.0,1.0);
glTexCoord2f(1,0);
glVertex2f(512,-512);
// glColor3f(1.0,0.0,0.0);
glEnd(); //关闭纹理映射
glEnable(GL_BLEND); //启用混色效果
if(m_bBrush)
// glBlendFunc(GL_ONE,GL_ONE);// 当画刷为真时具体混色方案,第一个参数是源融合因子,后一个是目标融合因子
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
else
glBlendFunc(GL_SRC_COLOR,GL_ONE_MINUS_SRC_COLOR); //当画刷不为真时,采用另一种混色方案
glBindTexture(GL_TEXTURE_2D,m_texture[0]);
glBegin(GL_TRIANGLES);
// glBegin(GL_QUADS);
for(int i=m_iDrawStartPoint;i<m_iSimStartPoint;i++)
{
pNum = i%10000;
glColor3fv(m_ColorPoint[pNum].color);
glTexCoord2f(0,0);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
glTexCoord2f(0,0.5);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
glTexCoord2f(0.5,0.5);
glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
// glTexCoord2f(1,0);
// glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
}
glEnd();
glBindTexture(GL_TEXTURE_2D,m_texture[1]);
glCopyTexSubImage2D(GL_TEXTURE_2D,0,512-m_iWindowWidth/2,512-m_iWindowHeight/2,0,0,m_iWindowWidth,m_iWindowHeight);
m_iDrawStartPoint=m_iSimStartPoint;
glBindTexture(GL_TEXTURE_2D,m_texture[0]);
// glBegin(GL_QUADS);
glBegin(GL_TRIANGLES);
for(i=m_iSimStartPoint;i<m_iPointNum;i++)
{
pNum = i%10000;
glColor3fv(m_ColorPoint[pNum].color);
glTexCoord2f(0,0);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
glTexCoord2f(0,0.5);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
glTexCoord2f(0.5,0.5);
glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
// glTexCoord2f(1,0);
// glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
}
glEnd();
glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
// glColor3f(0.9,0.9,0.8);
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
glVertex2f(-m_iWindowWidth/2,-m_iWindowHeight/2);
glVertex2f(m_iWindowWidth/2,-m_iWindowHeight/2);
glVertex2f(m_iWindowWidth/2,m_iWindowHeight/2);
glVertex2f(-m_iWindowWidth/2,m_iWindowHeight/2);
glEnd();
glDisable(GL_BLEND);
}*/
int CWsqView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
g_pView = (CView*)this;
// TODO: Add your specialized creation code here
m_hWnd = GetSafeHwnd();
m_hDC = ::GetDC(m_hWnd); //取得设备描述表
if(SetWindowPixelFormat(m_hDC)==FALSE)
return 0;
if(CreateViewGLContext(m_hDC)==FALSE)
return 0;
LoadTextures(); //调用载入纹理函数
if(m_bKey[VK_TAB])
glClear(GL_COLOR_BUFFER_BIT);
// SetTimer(0,30,NULL);
// Spread();
return 0;
}
void CWsqView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
if(wglGetCurrentContext() != NULL)
wglMakeCurrent(NULL,NULL);
if(m_hGLContext != NULL)
{
wglDeleteContext(m_hGLContext);
m_hGLContext = NULL;
}
}
void CWsqView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
m_hWnd = GetSafeHwnd();
m_hDC = ::GetDC(m_hWnd); //取得设备描述表
m_iWindowWidth = cx;
m_iWindowHeight = cy;
if(m_iWindowWidth < 10)
m_iWindowWidth = 10;
if(m_iWindowHeight < 10)
m_iWindowHeight = 10;
glViewport(0, 0, m_iWindowWidth, m_iWindowHeight); //设定视口
glMatrixMode(GL_PROJECTION);//指定哪一个矩阵是当前矩阵,对投影矩阵堆栈用随后的的矩阵操作
glLoadIdentity();
glOrtho(-m_iWindowWidth/2,m_iWindowWidth/2,-m_iWindowHeight/2,m_iWindowHeight/2,-100,100);
glMatrixMode(GL_MODELVIEW);//对模型视景矩阵堆栈应用随后的矩阵操作
}
void CWsqView::OnLButtonDown(UINT nFlags, CPoint point) //毛笔的捕捉
{
// TODO: Add your message handler code here and/or call default
m_LeftButtonDown = true;
m_fPointSize=1;
CView::OnLButtonDown(nFlags, point);
}
void CWsqView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_LeftButtonDown = false;
/*if(m_iPointNum>50)
{
for(int i=m_iPointNum-50;i<m_iPointNum;i++)
{
int pNum = m_iPointNum%10000;
if(m_ColorPoint[i].size>(m_iPointNum-i)/5)
m_ColorPoint[i].size=(m_iPointNum-i)/5;
}
}*/
CView::OnLButtonUp(nFlags, point);
}
void CWsqView::OnMouseMove(UINT nFlags, CPoint point) //毛笔的移动
{
// TODO: Add your message handler code here and/or call default
if(m_fPointSize>0)
{
float dx=(CPoint(m_MousePos-point)).x;
float dy=(CPoint(m_MousePos-point)).y;
float l=sqrt(dx*dx+dy*dy);
for(int i=0;i<int(l)+1;i++)
{
int pNum = m_iPointNum%10000;
m_ColorPoint[pNum].x=m_MousePos.x-m_iWindowWidth/2+dx/l*i;
m_ColorPoint[pNum].y=m_iWindowHeight/2-m_MousePos.y-dy/l*i;
m_ColorPoint[pNum].size=m_fPointSize;
for(int j=0;j<3;j++)
{
m_ColorPoint[pNum].color[j]=m_Color[j];
}
m_ColorPoint[pNum].life=30;
m_iPointNum++;
}
if(m_LeftButtonDown)
{
m_fPointSize-=(l-5)/10;
if(m_fPointSize>8)
m_fPointSize=8;
if(m_fPointSize<2)
m_fPointSize=2;
}
// Invalidate(0);
}
m_MousePos = point;
CView::OnMouseMove(nFlags, point);
}
void CWsqView::Spread() //毛笔写到纸上产生的蔓延开的效果
{
if(m_bKey[VK_TAB])
for(int i=m_iSimStartPoint;i<m_iPointNum;i++)
{
int pNum = i%10000;
m_ColorPoint[pNum].size*=1.01;
m_ColorPoint[pNum].color[0]-=0.001;
m_ColorPoint[pNum].color[1]-=0.001;
m_ColorPoint[pNum].color[2]-=0.001;
m_ColorPoint[pNum].life--;
if(m_ColorPoint[pNum].life<=0)
m_iSimStartPoint = i+1;
}
}
void CWsqView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if(!m_LeftButtonDown)
{
m_fPointSize-=(1+0.3*m_fPointSize);
if(m_fPointSize<0)
m_fPointSize=0;
}
Spread();
Invalidate(0);
// if(m_bKey[VK_TAB])
// SetTimer(3000,6000,NULL);
/* if(!m_LeftButtonDown)
{
m_fPointSize-=(1+0.3*m_fPointSize);
if(m_fPointSize<0)
m_fPointSize=0;
}
Invalidate(0);*/
CView::OnTimer(nIDEvent);
}
void CWsqView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
m_bKey[nChar]=true;
switch(nChar)
{
case ‘0‘:
m_bKey[VK_TAB]=true;
m_iSimStartPoint=m_iDrawStartPoint=m_iPointNum=0;
m_Color[0]=1;
m_Color[1]=1;
m_Color[2]=1;
break;
case ‘1‘:
m_Color[0]=0;
m_Color[1]=1;
m_Color[2]=1;
break;
case ‘2‘:
m_Color[0]=1;
m_Color[1]=0;
m_Color[2]=1;
break;
case ‘3‘:
m_Color[0]=1;
m_Color[1]=1;
m_Color[2]=0;
break;
case ‘4‘:
m_Color[0]=0;
m_Color[1]=0;
m_Color[2]=1;
break;
case ‘5‘:
m_Color[0]=1;
m_Color[1]=0;
m_Color[2]=0;
break;
case ‘6‘:
m_Color[0]=0;
m_Color[1]=1;
m_Color[2]=0;
break;
case ‘7‘:
m_Color[0]=0.2;
m_Color[1]=0.2;
m_Color[2]=0.2;
break;
case ‘8‘:
m_bKey[VK_TAB]=false;
m_Color[0]=1;
m_Color[1]=1;
m_Color[2]=1;
break;
case ‘9‘:
// glBindTexture(GL_TEXTURE_2D,m_texture[3]);
// DrawOtherScene();
m_Color[0]=0;
m_Color[1]=1;
m_Color[2]=1;
break;
case ‘B‘:
m_bBrush = !m_bBrush;
default:
;
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CWsqView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
m_bKey[nChar]=false;
CView::OnKeyUp(nChar, nRepCnt, nFlags);
}
// wsqView.cpp : implementation of the CWsqView class
//
#include "stdafx.h"
#include "wsq.h"
#include "wsqDoc.h"
#include "wsqView.h"
#include <MATH.H>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CWsqView
CView* g_pView;
bool resetView = false;
IMPLEMENT_DYNCREATE(CWsqView, CView)
//消息隐射
BEGIN_MESSAGE_MAP(CWsqView, CView)
//{{AFX_MSG_MAP(CWsqView)
//}}AFX_MSG_MAP
// Standard printing commands
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SIZE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
// ON_COMMAND(ID_FILE_NEW, CView::OnFileNew)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWsqView construction/destruction
BYTE tempdata[1024*1024*3]; //零时数据大小
CWsqView::CWsqView()
{
// TODO: add construction code here
m_LeftButtonDown = false; //初始化
for(int i=0;i<256;i++)
{
m_bKey[i]=false;
}
m_iPointNum = 0;
m_iSimStartPoint = 0;
m_iDrawStartPoint = 0;
m_fPointSize = 0;
m_Color[0]=1.0;
m_Color[1]=1.0;
m_Color[2]=1.0;
int life = 0;
m_bBrush = true;
}
CWsqView::~CWsqView()
{
}
BOOL CWsqView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style|=WS_CLIPSIBLINGS|WS_CLIPCHILDREN; //指定窗口风格
return CView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CWsqView drawing
void CWsqView::OnDraw(CDC* pDC) //绘图函数
{
CWsqDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if(resetView)
{
m_iSimStartPoint=m_iDrawStartPoint=m_iPointNum=0;//初始化
resetView = false;
}
// TODO: add draw code for native data here
if(pDoc->m_bImageChanged) //使得可以新建一个画图区
{
glBindTexture(GL_TEXTURE_2D,m_texture[1]);
m_ImageWidth=pDoc->m_ImageWidth;
m_ImageHeight=pDoc->m_ImageHeight;//纹理贴图
// if(m_bKey[VK_TAB])
// pDoc->m_bImageChanged = true;
glTexSubImage2D(GL_TEXTURE_2D, //子纹理
0,
512-m_ImageWidth/2,
512-m_ImageHeight/2,
m_ImageWidth,
m_ImageHeight,
GL_RGB,
GL_UNSIGNED_BYTE,
pDoc->m_pImage);//定义一个存在的二维纹理图像的一部分,但不能定义新的纹理
pDoc->m_bImageChanged = false;
// if(m_bKey[VK_TAB])
// pDoc->m_bImageChanged = true;
}
DrawScene();
// if(m_bKey[VK_TAB])
// pDoc->m_bImageChanged = true;
// Spread();
SetTimer(0,30,NULL); //定时30毫秒
SwapBuffers(m_hDC); //切换缓冲区 启用用双缓冲
}
/////////////////////////////////////////////////////////////////////////////
// CWsqView printing
//打印
BOOL CWsqView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
//重新打印
void CWsqView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CWsqView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
/////////////////////////////////////////////////////////////////////////////
// CWsqView diagnostics
#ifdef _DEBUG
void CWsqView::AssertValid() const
{
CView::AssertValid();
}
void CWsqView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CWsqDoc* CWsqView::GetDocument() // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWsqDoc)));
return (CWsqDoc*)m_pDocument;
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CWsqView message handlers
BOOL CWsqView::SetWindowPixelFormat(HDC hDC)
{
PIXELFORMATDESCRIPTOR pixelDesc; //像素图结构体
pixelDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); //说明该数据结构的长度
pixelDesc.nVersion = 1; //说明该数据结构的版本
pixelDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER | PFD_STEREO_DONTCARE; //指定像素缓存的属性:支持window,支持OpenGL,像素存为双缓存、立方体结构。
pixelDesc.iPixelType = PFD_TYPE_RGBA; // 指定RGBA模式
pixelDesc.cColorBits = 32; //说明颜色缓存中颜色位平面的个数
pixelDesc.cRedBits = 0;
pixelDesc.cRedShift = 0;
pixelDesc.cGreenBits = 0;
pixelDesc.cGreenShift = 0;
pixelDesc.cBlueBits = 0;
pixelDesc.cBlueShift = 0;
pixelDesc.cAlphaBits = 0;
pixelDesc.cAlphaShift = 0;
pixelDesc.cAccumBits = 64; //说明累积缓存位平面的个数
pixelDesc.cAccumRedBits = 0;
pixelDesc.cAccumGreenBits = 0;
pixelDesc.cAccumBlueBits = 0;
pixelDesc.cAccumAlphaBits = 0;
pixelDesc.cDepthBits = 32; //说明模板缓存的位数
pixelDesc.cStencilBits = 8; //说明模板缓存的位数
pixelDesc.cAuxBuffers = 0; //说明辅助缓存的个数
pixelDesc.iLayerType = PFD_MAIN_PLANE;
pixelDesc.bReserved = 0;
pixelDesc.dwLayerMask = 0;
pixelDesc.dwVisibleMask = 0;
pixelDesc.dwDamageMask = 0;
m_GLPixelIndex = ChoosePixelFormat(hDC,&pixelDesc);
if(m_GLPixelIndex == 0) // Choose default
{
m_GLPixelIndex = 1;
if(DescribePixelFormat(hDC,m_GLPixelIndex,
sizeof(PIXELFORMATDESCRIPTOR),&pixelDesc)==0)
return FALSE;
}
if(!SetPixelFormat(hDC,m_GLPixelIndex,&pixelDesc))
return FALSE;
return TRUE;
}
BOOL CWsqView::CreateViewGLContext(HDC hDC)
{
m_hGLContext = wglCreateContext(hDC); //创建RC
if(m_hGLContext==NULL) //创建失败
return FALSE;
if(wglMakeCurrent(hDC,m_hGLContext)==FALSE) //选为当前RC失败
return FALSE;
return TRUE;
}
void CWsqView::LoadTextures() //载入纹理
{
AUX_RGBImageRec *TextureImage; //颜色对象
TextureImage = auxDIBImageLoad(_T("Data/tree.bmp")); //载入bmp图,并转换为纹理
glGenTextures(1,&m_texture[0]); // 创建一个新纹理
glBindTexture(GL_TEXTURE_2D,m_texture[0]); //关联一个纹理
//设定纹理参数
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR); // 创建使用线性Mipmap过滤器过滤得纹理,即使用线性插值计算两个图像中的每个图像的纹素值,然后在两个图像间进行线性插值
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); //放大、缩小纹理滤波
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); //使用重复贴图
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,TextureImage->sizeX,TextureImage->sizeY,GL_RGB,GL_UNSIGNED_BYTE,TextureImage->data);//创建二维多重映射
//glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);
free(TextureImage->data); //释放数据
free(TextureImage); //释放纹理对象
TextureImage = auxDIBImageLoad(_T("Data/Terrain.bmp")); //载入bmp图,并转换为纹理
glGenTextures(1,&m_texture[1]);// 创建纹理
glBindTexture(GL_TEXTURE_2D,m_texture[1]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); // 创建使用临近过滤器过滤得纹理,选择最接近像素中心的纹素进行放大或缩小
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);//不使用重复贴图
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,1024,1024,GL_RGB,GL_UNSIGNED_BYTE,tempdata); //定义分辨率逐渐减小到2*2的多重图像,并将原图缩放到最接近2的幂次方的尺寸上
// glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);
free(TextureImage->data);
free(TextureImage);
TextureImage = auxDIBImageLoad(_T("Data/grass1.bmp")); //载入bmp图,并转换为纹理
glGenTextures(1,&m_texture[2]); // 创建纹理
glBindTexture(GL_TEXTURE_2D,m_texture[2]);
free(TextureImage->data);
free(TextureImage);
TextureImage = auxDIBImageLoad(_T("Data/Butterfly3.bmp")); //载入bmp图,并转换为纹理
glGenTextures(1,&m_texture[3]);// 创建纹理
glBindTexture(GL_TEXTURE_2D,m_texture[3]);
gluBuild2DMipmaps(GL_TEXTURE_2D,3,1024,1024,GL_RGB,GL_UNSIGNED_BYTE,tempdata); //定义分辨率逐渐减小到2*2的多重图像,并将原图缩放到最接近2的幂次方的尺寸上
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);
free(TextureImage->data);
free(TextureImage);
/* int Status=FALSE; // Status Indicator
AUX_RGBImageRec *TextureImage[4]; // Create Storage Space For The Textures
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
if (TextureImage[0]=LoadBMP("Data/Particle.bmp")) // Load Particle Texture
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[0]); // Create One Texture
glBindTexture(GL_TEXTURE_2D, texture[0]);
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, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
}
if (TextureImage[1]=LoadBMP("Data/grass1.bmp")) // Load Particle Texture
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[1]); // Create One Texture
glBindTexture(GL_TEXTURE_2D, texture[1]);
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, 3, 1024, 1024, 0, GL_RGB, GL_UNSIGNED_BYTE, tempdata);
}
if (TextureImage[2]=LoadBMP("Data/Terrain.bmp")) // Load Particle Texture
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[2]); // Create One Texture
glBindTexture(GL_TEXTURE_2D, texture[2]);
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, 3, TextureImage[2]->sizeX, TextureImage[2]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[2]->data);
}
if (TextureImage[3]=LoadBMP("Data/tree.bmp")) // Load Particle Texture
{
Status=TRUE; // Set The Status To TRUE
glGenTextures(1, &texture[3]); // Create One Texture
glBindTexture(GL_TEXTURE_2D, texture[3]);
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, 3, TextureImage[3]->sizeX, TextureImage[3]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[3]->data);
}
if (TextureImage[0]) // If Texture Exists
{
if (TextureImage[0]->data) // If Texture Image Exists
{
free(TextureImage[0]->data); // Free The Texture Image Memory
}
free(TextureImage[0]); // Free The Image Structure
}
if (TextureImage[1]) // If Texture Exists
{
if (TextureImage[1]->data) // If Texture Image Exists
{
free(TextureImage[1]->data); // Free The Texture Image Memory
}
free(TextureImage[1]); // Free The Image Structure
}
if (TextureImage[2]) // If Texture Exists
{
if (TextureImage[2]->data) // If Texture Image Exists
{
free(TextureImage[2]->data); // Free The Texture Image Memory
}
free(TextureImage[2]); // Free The Image Structure
}
if (TextureImage[3]) // If Texture Exists
{
if (TextureImage[3]->data) // If Texture Image Exists
{
free(TextureImage[3]->data); // Free The Texture Image Memory
}
free(TextureImage[3]); // Free The Image Structure
}
return Status; */ // Return The Status
}
void CWsqView::DrawScene()//绘制场景
{
int pNum;
glClearColor(0,0,0,0); //设置背景颜色
// if(m_bKey[VK_TAB])
// glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
glLoadIdentity(); //重置当前的模型观察矩阵
glEnable(GL_TEXTURE_2D); //启用二维纹理映射
glBindTexture(GL_TEXTURE_2D,m_texture[1]); //创建纹理
glColor3f(1,1,1); //设置颜色为白色
glBegin(GL_QUADS); //绘制四边形
glTexCoord2f(0,0); //设定当前纹理坐标
glVertex2f(-512,-512); //指定顶点,即纹理坐标(0,0)被映射到物体顶点(-512,-512)上
// glColor3f(1.0,0.0,0.0);
glTexCoord2f(0,1); //设定当前纹理坐标
glVertex2f(-512,512); //指定顶点
// glColor3f(0.0,1.0,0.0);
glTexCoord2f(1,1);
glVertex2f(512,512);
// glColor3f(0.0,0.0,1.0);
glTexCoord2f(1,0);
glVertex2f(512,-512);
// glColor3f(1.0,0.0,0.0);
glEnd(); //关闭纹理映射
glEnable(GL_BLEND); //启用混色效果
if(m_bBrush)
// glBlendFunc(GL_ONE,GL_ONE);// 当画刷为真时具体混色方案,第一个参数是源融合因子,后一个是目标融合因子
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
else
glBlendFunc(GL_SRC_COLOR,GL_ONE_MINUS_SRC_COLOR); //当画刷不为真时,采用另一种混色方案
glBindTexture(GL_TEXTURE_2D,m_texture[0]);
glBegin(GL_TRIANGLES);
// glBegin(GL_QUADS);
for(int i=m_iDrawStartPoint;i<m_iSimStartPoint;i++)
{
pNum = i%10000;
glColor3fv(m_ColorPoint[pNum].color);
glTexCoord2f(0,0);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
glTexCoord2f(0,0.5);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
glTexCoord2f(0.5,0.5);
glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
// glTexCoord2f(1,0);
// glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
}
glEnd();
glBindTexture(GL_TEXTURE_2D,m_texture[1]);
glCopyTexSubImage2D(GL_TEXTURE_2D,0,512-m_iWindowWidth/2,512-m_iWindowHeight/2,0,0,m_iWindowWidth,m_iWindowHeight);
m_iDrawStartPoint=m_iSimStartPoint;
glBindTexture(GL_TEXTURE_2D,m_texture[0]);
// glBegin(GL_QUADS);
glBegin(GL_TRIANGLES);
for(int i=m_iSimStartPoint;i<m_iPointNum;i++)
{
pNum = i%10000;
glColor3fv(m_ColorPoint[pNum].color);
//glTexCoord2f(0,0);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
//glTexCoord2f(0,0.5);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
//glTexCoord2f(0.5,0.5);
glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
// glTexCoord2f(1,0);
// glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
}
glEnd();
glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
if(m_bKey[VK_TAB])
glColor3f(0.9,0.9,0.8);
else
glColor3f(1.0,1.0,1.0);
// Spread();
glBegin(GL_QUADS);
glVertex2f(-m_iWindowWidth/2,-m_iWindowHeight/2);
glVertex2f(m_iWindowWidth/2,-m_iWindowHeight/2);
glVertex2f(m_iWindowWidth/2,m_iWindowHeight/2);
glVertex2f(-m_iWindowWidth/2,m_iWindowHeight/2);
glEnd();
glDisable(GL_BLEND);
}
/*void CWsqView::DrawOtherScene() 其他场景绘制
{
int pNum;
glClearColor(0,0,0,0); //设置背景颜色
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
glLoadIdentity(); //重置当前的模型观察矩阵
glEnable(GL_TEXTURE_2D); //启用二维纹理映射
glBindTexture(GL_TEXTURE_2D,m_texture[1]); //创建纹理
glColor3f(1,1,1); //设置颜色为白色
glBegin(GL_QUADS); //绘制四边形
glTexCoord2f(0,0); //设定当前纹理坐标
glVertex2f(-512,-512); //指定顶点,即纹理坐标(0,0)被映射到物体顶点(-512,-512)上
// glColor3f(1.0,0.0,0.0);
glTexCoord2f(0,1); //设定当前纹理坐标
glVertex2f(-512,512); //指定顶点
// glColor3f(0.0,1.0,0.0);
glTexCoord2f(1,1);
glVertex2f(512,512);
// glColor3f(0.0,0.0,1.0);
glTexCoord2f(1,0);
glVertex2f(512,-512);
// glColor3f(1.0,0.0,0.0);
glEnd(); //关闭纹理映射
glEnable(GL_BLEND); //启用混色效果
if(m_bBrush)
// glBlendFunc(GL_ONE,GL_ONE);// 当画刷为真时具体混色方案,第一个参数是源融合因子,后一个是目标融合因子
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
else
glBlendFunc(GL_SRC_COLOR,GL_ONE_MINUS_SRC_COLOR); //当画刷不为真时,采用另一种混色方案
glBindTexture(GL_TEXTURE_2D,m_texture[0]);
glBegin(GL_TRIANGLES);
// glBegin(GL_QUADS);
for(int i=m_iDrawStartPoint;i<m_iSimStartPoint;i++)
{
pNum = i%10000;
glColor3fv(m_ColorPoint[pNum].color);
glTexCoord2f(0,0);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
glTexCoord2f(0,0.5);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
glTexCoord2f(0.5,0.5);
glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
// glTexCoord2f(1,0);
// glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
}
glEnd();
glBindTexture(GL_TEXTURE_2D,m_texture[1]);
glCopyTexSubImage2D(GL_TEXTURE_2D,0,512-m_iWindowWidth/2,512-m_iWindowHeight/2,0,0,m_iWindowWidth,m_iWindowHeight);
m_iDrawStartPoint=m_iSimStartPoint;
glBindTexture(GL_TEXTURE_2D,m_texture[0]);
// glBegin(GL_QUADS);
glBegin(GL_TRIANGLES);
for(i=m_iSimStartPoint;i<m_iPointNum;i++)
{
pNum = i%10000;
glColor3fv(m_ColorPoint[pNum].color);
glTexCoord2f(0,0);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
glTexCoord2f(0,0.5);
glVertex2f(m_ColorPoint[pNum].x-m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
glTexCoord2f(0.5,0.5);
glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y+m_ColorPoint[pNum].size);
// glTexCoord2f(1,0);
// glVertex2f(m_ColorPoint[pNum].x+m_ColorPoint[pNum].size,m_ColorPoint[pNum].y-m_ColorPoint[pNum].size);
}
glEnd();
glDisable(GL_TEXTURE_2D);
glBlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ZERO);
// glColor3f(0.9,0.9,0.8);
glColor3f(1.0,1.0,1.0);
glBegin(GL_QUADS);
glVertex2f(-m_iWindowWidth/2,-m_iWindowHeight/2);
glVertex2f(m_iWindowWidth/2,-m_iWindowHeight/2);
glVertex2f(m_iWindowWidth/2,m_iWindowHeight/2);
glVertex2f(-m_iWindowWidth/2,m_iWindowHeight/2);
glEnd();
glDisable(GL_BLEND);
}*/
int CWsqView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
g_pView = (CView*)this;
// TODO: Add your specialized creation code here
m_hWnd = GetSafeHwnd();
m_hDC = ::GetDC(m_hWnd); //取得设备描述表
if(SetWindowPixelFormat(m_hDC)==FALSE)
return 0;
if(CreateViewGLContext(m_hDC)==FALSE)
return 0;
LoadTextures(); //调用载入纹理函数
if(m_bKey[VK_TAB])
glClear(GL_COLOR_BUFFER_BIT);
// SetTimer(0,30,NULL);
// Spread();
return 0;
}
void CWsqView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
if(wglGetCurrentContext() != NULL)
wglMakeCurrent(NULL,NULL);
if(m_hGLContext != NULL)
{
wglDeleteContext(m_hGLContext);
m_hGLContext = NULL;
}
}
void CWsqView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
m_hWnd = GetSafeHwnd();
m_hDC = ::GetDC(m_hWnd); //取得设备描述表
m_iWindowWidth = cx;
m_iWindowHeight = cy;
if(m_iWindowWidth < 10)
m_iWindowWidth = 10;
if(m_iWindowHeight < 10)
m_iWindowHeight = 10;
glViewport(0, 0, m_iWindowWidth, m_iWindowHeight); //设定视口
glMatrixMode(GL_PROJECTION);//指定哪一个矩阵是当前矩阵,对投影矩阵堆栈用随后的的矩阵操作
glLoadIdentity();
glOrtho(-m_iWindowWidth/2,m_iWindowWidth/2,-m_iWindowHeight/2,m_iWindowHeight/2,-100,100);
glMatrixMode(GL_MODELVIEW);//对模型视景矩阵堆栈应用随后的矩阵操作
}
void CWsqView::OnLButtonDown(UINT nFlags, CPoint point) //毛笔的捕捉
{
// TODO: Add your message handler code here and/or call default
m_LeftButtonDown = true;
m_fPointSize=1;
CView::OnLButtonDown(nFlags, point);
}
void CWsqView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_LeftButtonDown = false;
/*if(m_iPointNum>50)
{
for(int i=m_iPointNum-50;i<m_iPointNum;i++)
{
int pNum = m_iPointNum%10000;
if(m_ColorPoint[i].size>(m_iPointNum-i)/5)
m_ColorPoint[i].size=(m_iPointNum-i)/5;
}
}*/
CView::OnLButtonUp(nFlags, point);
}
void CWsqView::OnMouseMove(UINT nFlags, CPoint point) //毛笔的移动
{
// TODO: Add your message handler code here and/or call default
if(m_fPointSize>0)
{
float dx=(CPoint(m_MousePos-point)).x;
float dy=(CPoint(m_MousePos-point)).y;
float l=sqrt(dx*dx+dy*dy);
for(int i=0;i<int(l)+1;i++)
{
int pNum = m_iPointNum%10000;
m_ColorPoint[pNum].x=m_MousePos.x-m_iWindowWidth/2+dx/l*i;
m_ColorPoint[pNum].y=m_iWindowHeight/2-m_MousePos.y-dy/l*i;
m_ColorPoint[pNum].size=m_fPointSize;
for(int j=0;j<3;j++)
{
m_ColorPoint[pNum].color[j]=m_Color[j];
}
m_ColorPoint[pNum].life=30;
m_iPointNum++;
}
if(m_LeftButtonDown)
{
m_fPointSize-=(l-5)/10;
if(m_fPointSize>8)
m_fPointSize=8;
if(m_fPointSize<2)
m_fPointSize=2;
}
// Invalidate(0);
}
m_MousePos = point;
CView::OnMouseMove(nFlags, point);
}
void CWsqView::Spread() //毛笔写到纸上产生的蔓延开的效果
{
if(m_bKey[VK_TAB])
for(int i=m_iSimStartPoint;i<m_iPointNum;i++)
{
int pNum = i%10000;
m_ColorPoint[pNum].size*=1.01;
m_ColorPoint[pNum].color[0]-=0.001;
m_ColorPoint[pNum].color[1]-=0.001;
m_ColorPoint[pNum].color[2]-=0.001;
m_ColorPoint[pNum].life--;
if(m_ColorPoint[pNum].life<=0)
m_iSimStartPoint = i+1;
}
}
void CWsqView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if(!m_LeftButtonDown)
{
m_fPointSize-=(1+0.3*m_fPointSize);
if(m_fPointSize<0)
m_fPointSize=0;
}
Spread();
Invalidate(0);
// if(m_bKey[VK_TAB])
// SetTimer(3000,6000,NULL);
/* if(!m_LeftButtonDown)
{
m_fPointSize-=(1+0.3*m_fPointSize);
if(m_fPointSize<0)
m_fPointSize=0;
}
Invalidate(0);*/
CView::OnTimer(nIDEvent);
}
void CWsqView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
m_bKey[nChar]=true;
switch(nChar)
{
case ‘0‘:
m_bKey[VK_TAB]=true;
m_iSimStartPoint=m_iDrawStartPoint=m_iPointNum=0;
m_Color[0]=1;
m_Color[1]=1;
m_Color[2]=1;
break;
case ‘1‘:
m_Color[0]=0;
m_Color[1]=1;
m_Color[2]=1;
break;
case ‘2‘:
m_Color[0]=1;
m_Color[1]=0;
m_Color[2]=1;
break;
case ‘3‘:
m_Color[0]=1;
m_Color[1]=1;
m_Color[2]=0;
break;
case ‘4‘:
m_Color[0]=0;
m_Color[1]=0;
m_Color[2]=1;
break;
case ‘5‘:
m_Color[0]=1;
m_Color[1]=0;
m_Color[2]=0;
break;
case ‘6‘:
m_Color[0]=0;
m_Color[1]=1;
m_Color[2]=0;
break;
case ‘7‘:
m_Color[0]=0.2;
m_Color[1]=0.2;
m_Color[2]=0.2;
break;
case ‘8‘:
m_bKey[VK_TAB]=false;
m_Color[0]=1;
m_Color[1]=1;
m_Color[2]=1;
break;
case ‘9‘:
// glBindTexture(GL_TEXTURE_2D,m_texture[3]);
// DrawOtherScene();
m_Color[0]=0;
m_Color[1]=1;
m_Color[2]=1;
break;
case ‘B‘:
m_bBrush = !m_bBrush;
default:
;
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CWsqView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
m_bKey[nChar]=false;
CView::OnKeyUp(nChar, nRepCnt, nFlags);
}
------------------------------
调试一路下来了,赶紧看看结果,非常激动人心的时刻到来了
由于自己写的不好,但是那些功能全部实现了,有毛笔字写的好一定发给我啊