shader實作類:
#pragma once
#include <assert.h>
class ShaderId
{
public:
ShaderId()
{
_shaderId = -1;
}
int _shaderId;
};
/**
* 程式
*/
class ProgramId
{
public:
int _programId;
ShaderId _vertex;
ShaderId _fragment;
public:
ProgramId()
{
_programId = -1;
}
public:
/**
* 加載函數
*/
bool createProgram(const char* vertex, const char* fragment)
{
bool error = false;
do
{
if (vertex)
{
_vertex._shaderId = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(_vertex._shaderId, 1, &vertex, 0);
glCompileShader(_vertex._shaderId);
GLint compileStatus;
glGetShaderiv(_vertex._shaderId, GL_COMPILE_STATUS, &compileStatus);
error = compileStatus == GL_FALSE;
if (error)
{
GLchar messages[256];
glGetShaderInfoLog(_vertex._shaderId, sizeof(messages), 0, messages);
assert(messages && 0 != 0);
break;
}
}
if (fragment)
{
_fragment._shaderId = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(_fragment._shaderId, 1, &fragment, 0);
glCompileShader(_fragment._shaderId);
GLint compileStatus;
glGetShaderiv(_fragment._shaderId, GL_COMPILE_STATUS, &compileStatus);
error = compileStatus == GL_FALSE;
if (error)
{
GLchar messages[256];
glGetShaderInfoLog(_fragment._shaderId, sizeof(messages), 0, messages);
assert(messages && 0 != 0);
break;
}
}
_programId = glCreateProgram();
if (_vertex._shaderId)
{
glAttachShader(_programId, _vertex._shaderId);
}
if (_fragment._shaderId)
{
glAttachShader(_programId, _fragment._shaderId);
}
glLinkProgram(_programId);
GLint linkStatus;
glGetProgramiv(_programId, GL_LINK_STATUS, &linkStatus);
if (linkStatus == GL_FALSE)
{
GLchar messages[256];
glGetProgramInfoLog(_programId, sizeof(messages), 0, messages);
break;
}
glUseProgram(_programId);
} while (false);
if (error)
{
if (_fragment._shaderId)
{
glDeleteShader(_fragment._shaderId);
_fragment._shaderId = 0;
}
if (_vertex._shaderId)
{
glDeleteShader(_vertex._shaderId);
_vertex._shaderId = 0;
}
if (_programId)
{
glDeleteProgram(_programId);
_programId = 0;
}
}
return true;
}
/**
* 使用程式
*/
virtual void begin()
{
glUseProgram(_programId);
}
/**
* 使用完成
*/
virtual void end()
{
glUseProgram(0);
}
};
class PROGRAM_P2_C4 :public ProgramId
{
public:
typedef int attribute;
typedef int uniform;
public:
attribute _position;
uniform _color;
uniform _MVP;
public:
PROGRAM_P2_C4()
{
_position = -1;
_color = -1;
_MVP = -1;
}
~PROGRAM_P2_C4()
{
}
/// 初始化函數
virtual bool initialize()
{
const char* vs =
{
"precision lowp float; "
"uniform mat4 _MVP;"
"attribute vec2 _position;"
"void main()"
"{"
" vec4 pos = vec4(_position,0,1);"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"precision lowp float; "
"uniform vec4 _color;"
"void main()"
"{"
" gl_FragColor = _color;"
"}"
};
bool res = createProgram(vs, ps);
if (res)
{
_position = glGetAttribLocation(_programId, "_position");
_color = glGetUniformLocation(_programId, "_color");
_MVP = glGetUniformLocation(_programId, "_MVP");
}
return res;
}
/**
* 使用程式
*/
virtual void begin()
{
glUseProgram(_programId);
glEnableVertexAttribArray(_position);
}
/**
* 使用完成
*/
virtual void end()
{
glDisableVertexAttribArray(_position);
glUseProgram(0);
}
};
class PROGRAM_P2_AC4 :public ProgramId
{
public:
typedef int attribute;
typedef int uniform;
public:
attribute _position;
attribute _color;
uniform _MVP;
public:
PROGRAM_P2_AC4()
{
_position = -1;
_color = -1;
_MVP = -1;
}
~PROGRAM_P2_AC4()
{
}
/// 初始化函數
virtual bool initialize()
{
const char* vs =
{
"precision lowp float; "
"uniform mat4 _MVP;"
"attribute vec2 _position;"
"attribute vec4 _color;"
"varying vec4 _outColor;"
"void main()"
"{"
" vec4 pos = vec4(_position,0,1);"
" _outColor = _color;"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"precision lowp float; "
"varying vec4 _outColor;"
"void main()"
"{"
" gl_FragColor = _outColor;"
"}"
};
bool res = createProgram(vs, ps);
if (res)
{
_position = glGetAttribLocation(_programId, "_position");
_color = glGetAttribLocation(_programId, "_color");
_MVP = glGetUniformLocation(_programId, "_MVP");
}
return res;
}
/**
* 使用程式
*/
virtual void begin()
{
glUseProgram(_programId);
glEnableVertexAttribArray(_position);
glEnableVertexAttribArray(_color);
}
/**
* 使用完成
*/
virtual void end()
{
glDisableVertexAttribArray(_position);
glDisableVertexAttribArray(_color);
glUseProgram(0);
}
};
class PROGRAM_P2_UV_AC4 :public ProgramId
{
public:
typedef int attribute;
typedef int uniform;
public:
attribute _position;
attribute _color;
attribute _uv;
uniform _MVP;
uniform _texture;
public:
PROGRAM_P2_UV_AC4()
{
_position = -1;
_color = -1;
_uv = -1;
_texture = -1;
_MVP = -1;
}
~PROGRAM_P2_UV_AC4()
{
}
/// 初始化函數
virtual bool initialize()
{
const char* vs =
{
"precision lowp float; "
"uniform mat4 _MVP;"
"attribute vec2 _position;"
"attribute vec2 _uv;"
"attribute vec4 _color;"
"varying vec4 _outColor;"
"varying vec2 _outUV;"
"void main()"
"{"
" vec4 pos = vec4(_position,0,1);"
" _outColor = _color;"
" _outUV = _uv;"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"precision lowp float; "
"uniform sampler2D _texture;\n"
"varying vec4 _outColor;\n"
"varying vec2 _outUV;\n"
"void main()"
"{"
" vec4 tColor = texture2D(_texture,_outUV);\n"
" gl_FragColor = tColor * _outColor;\n"
"}"
};
bool res = createProgram(vs, ps);
if (res)
{
_position = glGetAttribLocation(_programId, "_position");
_color = glGetAttribLocation(_programId, "_color");
_uv = glGetAttribLocation(_programId, "_uv");
_texture = glGetUniformLocation(_programId, "_texture");
_MVP = glGetUniformLocation(_programId, "_MVP");
}
return res;
}
/**
* 使用程式
*/
virtual void begin()
{
glUseProgram(_programId);
glEnableVertexAttribArray(_position);
glEnableVertexAttribArray(_uv);
glEnableVertexAttribArray(_color);
}
/**
* 使用完成
*/
virtual void end()
{
glDisableVertexAttribArray(_position);
glDisableVertexAttribArray(_uv);
glDisableVertexAttribArray(_color);
glUseProgram(0);
}
};
視窗實作類:
#pragma once
#include <Windows.h>
#include <tchar.h>
#include <math.h>
#include <EGL/egl.h>
#include <gles2/gl2.h>
#include "freeImage/FreeImage.h"
#include "CELLMath.hpp"
#include "CELLShader.hpp"
namespace CELL
{
class CELLWinApp
{
public:
//! 執行個體句柄
HINSTANCE _hInstance;
//! 視窗句柄
HWND _hWnd;
//! 視窗的高度
int _width;
//! 視窗的寬度
int _height;
/// for gles2.0
EGLConfig _config;
EGLSurface _surface;
EGLContext _context;
EGLDisplay _display;
//! 增加shader
PROGRAM_P2_UV_AC4 _shader;
unsigned _textureId;
public:
CELLWinApp(HINSTANCE hInstance)
:_hInstance(hInstance)
{
WNDCLASSEX winClass;
winClass.lpszClassName = _T("CELLWinApp");
winClass.cbSize = sizeof(winClass);
winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
winClass.lpfnWndProc = wndProc;
winClass.hInstance = hInstance;
winClass.hIcon = 0;
winClass.hIconSm = 0;
winClass.hCursor = LoadCursor(hInstance, IDC_ARROW);
winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winClass.lpszMenuName = NULL;
winClass.cbClsExtra = 0;
winClass.cbWndExtra = 0;
RegisterClassEx(&winClass);
_textureId = 0;
}
virtual ~CELLWinApp()
{
UnregisterClass(_T("CELLWinApp"), _hInstance);
}
/**
* 初始化 OpenGLES2.0
*/
bool initOpenGLES20()
{
const EGLint attribs[] =
{
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_NONE
};
EGLint format(0);
EGLint numConfigs(0);
EGLint major;
EGLint minor;
//! 1
_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
//! 2init
eglInitialize(_display, &major, &minor);
//! 3
eglChooseConfig(_display, attribs, &_config, 1, &numConfigs);
eglGetConfigAttrib(_display, _config, EGL_NATIVE_VISUAL_ID, &format);
//! 4
_surface = eglCreateWindowSurface(_display, _config, _hWnd, NULL);
//! 5
EGLint attr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
_context = eglCreateContext(_display, _config, 0, attr);
//! 6
if (eglMakeCurrent(_display, _surface, _surface, _context) == EGL_FALSE)
{
return false;
}
eglQuerySurface(_display, _surface, EGL_WIDTH, &_width);
eglQuerySurface(_display, _surface, EGL_HEIGHT, &_height);
return true;
}
/**
* 銷毀OpenGLES2.0
*/
void destroyOpenGLES20()
{
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;
}
virtual unsigned loadTexture(const char* fileName)
{
unsigned textureId = 0;
//1 擷取圖檔格式
FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
//2 加載圖檔
FIBITMAP *dib = FreeImage_Load(fifmt, fileName, 0);
//3 轉化為rgb 24色
dib = FreeImage_ConvertTo24Bits(dib);
//4 擷取資料指針
BYTE *pixels = (BYTE*)FreeImage_GetBits(dib);
int width = FreeImage_GetWidth(dib);
int height = FreeImage_GetHeight(dib);
for (size_t i = 0; i < width * height * 3; i += 3)
{
BYTE temp = pixels[i];
pixels[i] = pixels[i + 2];
pixels[i + 2] = temp;
}
/**
* 産生一個紋理Id,可以認為是紋理句柄,後面的操作将書用這個紋理id
*/
glGenTextures(1, &textureId);
/**
* 使用這個紋理id,或者叫綁定(關聯)
*/
glBindTexture(GL_TEXTURE_2D, textureId);
/**
* 指定紋理的放大,縮小濾波,使用線性方式,即當圖檔放大的時候插值方式
*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
/*
*當紋理坐标超出[0,0]到[1,1]的範圍時紋理坐标的處理由wrap參數指定,
*1--GL_REPEAT:坐标的整數部分被忽略,重複紋理,這是OpenGL紋理預設的處理方式.
*2--GL_MIRRORED_REPEAT: 紋理也會被重複,但是當紋理坐标的整數部分是奇數時會使用鏡像重複。
*3--GL_CLAMP_TO_EDGE: 坐标會被截斷到[0,1]之間。結果是坐标值大的被截斷到紋理的邊緣部分,形成了一個拉伸的邊緣(stretched edge pattern)。
*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
/**
* 将圖檔的rgb資料上傳給opengl.
*/
glTexImage2D(
GL_TEXTURE_2D, //! 指定是二維圖檔
0, //! 指定為第一級别,紋理可以做mipmap,即lod,離近的就采用級别大的,遠則使用較小的紋理
GL_RGB, //! 紋理的使用的存儲格式
width, //! 寬度,老一點的顯示卡,不支援不規則的紋理,即寬度和高度不是2^n。
height, //! 寬度,老一點的顯示卡,不支援不規則的紋理,即寬度和高度不是2^n。
0, //! 是否的邊
GL_RGB, //! 資料的格式,bmp中,windows,作業系統中存儲的資料是bgr格式
GL_UNSIGNED_BYTE, //! 資料是8bit資料
pixels
);
char subData[100 * 100 * 3];
memset(subData, 255, sizeof(subData));
/**
功能:提供修改圖像的功能,因為修改一個紋理比重新建立一個紋理開銷小很多,對于一些視訊捕捉程式可以先将視訊圖像存儲在更大的初始圖像中
(圖像大小要是2^n,opengl2.0後沒有這個限制),建立一個渲染用的紋理,然後反複調用glTexSubImage2D(修改的圖像區域不用是2^n)函數從視訊圖像區域讀取到渲染
紋理圖像中,渲染用的紋理圖像隻需要建立一次即可。
函數原型 glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
target:必須是glCopyTexImage2D中對應的target可用值
level:mipmap等級
xoffset,yoffset是要修改的圖像左上角偏移,width,height是要修改的圖像寬高像素修改的範圍在原圖之外并不受影響
format,type:表示圖像的資料格式和類型
pixels:子圖像的紋理資料
*/
glTexSubImage2D(GL_TEXTURE_2D, 0, 100, 100, 100, 100, GL_RGB, GL_UNSIGNED_BYTE, subData);
/**
* 釋放記憶體
*/
FreeImage_Unload(dib);
return textureId;
}
protected:
static LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
CELLWinApp* pThis = (CELLWinApp*)GetWindowLong(hWnd, GWL_USERDATA);
if (pThis)
{
return pThis->onEvent(hWnd, msg, wParam, lParam);
}
if (WM_CREATE == msg)
{
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
SetWindowLong(hWnd, GWL_USERDATA, (DWORD_PTR)pCreate->lpCreateParams);
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
public:
/**
* 事件函數
*/
virtual LRESULT onEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CLOSE:
case WM_DESTROY:
{
::PostQuitMessage(0);
}
break;
case WM_MOUSEMOVE:
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return S_OK;
}
virtual void render()
{
struct Vertex
{
CELL::float2 pos;
CELL::float2 uv;
CELL::Rgba4Byte color;
};
//! 清空緩沖區
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
//! 視口,在Windows視窗指定的位置和大小上繪制OpenGL内容
glViewport(0, 0, _width, _height);
//! 建立一個投影矩陣
glBindTexture(GL_TEXTURE_2D, _textureId);
CELL::matrix4 screenProj = CELL::ortho<float>(0, float(_width), float(_height), 0, -100.0f, 100);
_shader.begin();
{
float x = 100;
float y = 100;
float w = 400;
float h = 400;
float rt = 2;
Vertex vertex[] =
{
CELL::float2(x, y), CELL::float2(0, 0), CELL::Rgba4Byte(255, 255, 255, 255),
CELL::float2(x + w, y), CELL::float2(rt, 0), CELL::Rgba4Byte(255, 255, 255, 255),
CELL::float2(x, y + h), CELL::float2(0, rt), CELL::Rgba4Byte(255, 255, 255, 255),
CELL::float2(x + w, y + h), CELL::float2(rt, rt), CELL::Rgba4Byte(255, 255, 255, 255),
};
CELL::matrix4 matMVP = screenProj;
glUniformMatrix4fv(_shader._MVP, 1, false, matMVP.data());
glUniform1i(_shader._texture, 0);
glVertexAttribPointer(_shader._position, 2, GL_FLOAT, false, sizeof(Vertex), vertex);
glVertexAttribPointer(_shader._uv, 2, GL_FLOAT, false, sizeof(Vertex), &vertex[0].uv);
glVertexAttribPointer(_shader._color, 4, GL_UNSIGNED_BYTE, true, sizeof(Vertex), &vertex[0].color);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
_shader.end();
}
/**
* 主函數
*/
int main(int width, int height)
{
_hWnd = CreateWindowEx(NULL,
_T("CELLWinApp"),
_T("CELLWinApp"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
width,
height,
NULL,
NULL,
_hInstance,
this
);
if (_hWnd == 0)
{
return -1;
}
UpdateWindow(_hWnd);
ShowWindow(_hWnd, SW_SHOW);
if (!initOpenGLES20())
{
return false;
}
_shader.initialize();
_textureId = loadTexture("Debug/data/image/5.jpg");
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (msg.message == WM_DESTROY ||
msg.message == WM_CLOSE)
{
break;
}
/**
* 有消息,處理消息,無消息,則進行渲染繪制
*/
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
render();
eglSwapBuffers(_display, _surface);
}
}
/**
* 銷毀OpenGLES20
*/
destroyOpenGLES20();
return 0;
}
};
}
程式入口:
#include "CELLWinApp.hpp"
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
CELL::CELLWinApp app(hInstance);
app.main(800, 600);
return 0;
}
完整項目下載下傳位址:http://download.csdn.net/detail/hb707934728/9837754