OpenGLES---画一个矩形
Posted GameCocos2dx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGLES---画一个矩形相关的知识,希望对你有一定的参考价值。
{目录
RectShader
RectWin 窗口
画东西的几种类型
引用Shader中的属性(自己在Shader中写的一些需要传值的类型) glGetU/A...
设置Shader数据(Shader什么类型就用什么类型设置内容) glU/V...
}
-- RectShader
#include <gles2/gl2.h>
#include <assert.h>
typedef int uniform;
typedef int attribute;
typedef int location;
class ShaderId
{
public:
ShaderId(){id=-1;};
public:
int id;
};
class ShaderVeual
{
public:
ShaderVeual(){_programId=-1;}
public:
int _programId;
ShaderId _vertex;
ShaderId _fragment;
};
class RectShader
{
public:
ShaderVeual shaderveual;
attribute _position;
uniform _color;
uniform _MVP;
public :
RectShader(){
_position=-1;
_color=-1;
_MVP=-1;
}
void shaderInit(){
const char* vs = {
"precision lowp float;"//制定float的精度(lowp低精度)
"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;"
"}"
};
shaderveual=createProgram(vs,ps);
//获取属性的位置
_position = glGetAttribLocation(shaderveual._programId, "_position");
_color = glGetUniformLocation(shaderveual._programId,"_color");
_MVP = glGetUniformLocation(shaderveual._programId,"_MVP");
}
void begin(){
// 使用程序
glUseProgram(shaderveual._programId);
//启用顶点数组
glEnableVertexAttribArray(_position);
}
void end(){
//禁用顶点数组
glDisableVertexAttribArray(_position);
// 使用完成
glUseProgram(0);
}
virtual ShaderVeual createProgram( const char* vertex,const char* fragment ){
ShaderVeual program;
bool error = false;
do{
if (vertex){
// 创建Shader (GL_VERTEX_SHADER 顶点Shader,GL_FRAGMENT_SHADER 像素Shader)
program._vertex.id = glCreateShader( GL_VERTEX_SHADER );
//制定shader的源代码
glShaderSource( program._vertex.id, 1, &vertex, 0 );
//编译Shader
glCompileShader( program._vertex.id );
//检查编译状态
GLint compileStatus;
/** 获取Shader编译状态
* GL_COMPILE_STATUS 编译状态
* GL_INFO_LOG_LENGTH 0x8B84
* GL_SHADER_SOURCE_LENGTH 0x8B88
* GL_SHADER_COMPILER 0x8DFA
*/
glGetShaderiv( program._vertex.id, GL_COMPILE_STATUS, &compileStatus );
error = compileStatus == GL_FALSE;
if( error ){//如果编译失败
GLchar messages[256];
//获取编译日志
glGetShaderInfoLog( program._vertex.id, sizeof(messages), 0,messages);
//提升错误框
assert( messages && 0 != 0);
break;
}
}
//编译ps
if (fragment){
/***
* GL_FRAGMENT_SHADER 片段Shader/像素Shader
* glCreateShader( GL_VERTEX_SHADER );
*@reruen
****/
program._fragment.id = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( program._fragment.id, 1, &fragment, 0 ); //制定shader的源代码
glCompileShader( program._fragment.id );//编译Shader
GLint compileStatus;
glGetShaderiv( program._fragment.id, GL_COMPILE_STATUS, &compileStatus );//获取编译状态
error = compileStatus == GL_FALSE;
if( error ){
GLchar messages[256];
glGetShaderInfoLog( program._fragment.id, sizeof(messages), 0,messages);//获取Shader编译日志
assert( messages && 0 != 0);
break;
}
}
//创建一个程序(加载 vs ps)
program._programId = glCreateProgram( );
if (program._vertex.id) {
glAttachShader( program._programId, program._vertex.id);//加载 vs
}
if (program._fragment.id){
glAttachShader( program._programId, program._fragment.id);//加载 ps
}
//链接
glLinkProgram( program._programId );
GLint linkStatus;
glGetProgramiv( program._programId, GL_LINK_STATUS, &linkStatus );//获取链接程序状态
if (linkStatus == GL_FALSE){
GLchar messages[256];
glGetProgramInfoLog( program._programId, sizeof(messages), 0, messages);
break;
}
glUseProgram(program._programId);//使用 shads
} while(false);
if (error){
if (program._fragment.id != -1){
glDeleteShader(program._fragment.id);//删除像素Shader
program._fragment.id = 0;
}
if (program._vertex.id != -1){
glDeleteShader(program._vertex.id);//删除顶点Shader
program._vertex.id = 0;
}
if (program._programId != -1){
glDeleteProgram(program._programId);//删除程序
program._programId = 0;
}
}
return program;
}
};
---RectWin 窗口
#include "AppWin.hpp"
#include<vector>
#include <EGL/egl.h>
#include <gles2/gl2.h>
#include "freeImage/FreeImage.h"
#include "CELLMath.hpp"
#include "RectShader.hpp"
class RectWin :public AppWin
{
protected:
int _width; // 视口 宽度
int _height;// 视口 高度
EGLDisplay _display;
EGLContext _context;
EGLSurface _surface;
EGLConfig _config;
RectShader shader;
public:
RectWin(HINSTANCE hInstance):AppWin(hInstance){}
virtual ~RectWin(){}
void destroy(){
if (_display != EGL_NO_DISPLAY){//当前的Display 不等于null
//清楚绑定的 Surface Context
eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (_context != EGL_NO_CONTEXT){//不等于空Context
//销毁上下文
eglDestroyContext(_display, _context);
}
if (_surface != EGL_NO_SURFACE){//不等于空Surface
//销毁Surface
eglDestroySurface(_display, _surface);
}
//终止Dispay
eglTerminate(_display);
}
//把 Display Context Surface 设置成初始化
_display = EGL_NO_DISPLAY;
_context = EGL_NO_CONTEXT;
_surface = EGL_NO_SURFACE;
}
bool glInit(){
//1:获取 Display
_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
//2:初始化 egl
EGLint major;//返回主版本号
EGLint minor;//返回次版本号
eglInitialize(_display, &major, &minor);
//3:选择 Config
const EGLint attribs[] ={
//属性是一对一的初始化(类似与key->value)
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,//把数据画到窗口上
EGL_BLUE_SIZE, 8,//R 占8个比特位
EGL_GREEN_SIZE, 8,//G 占8个比特位
EGL_RED_SIZE, 8, //B 占8个比特位
EGL_DEPTH_SIZE,24,//深度值 占24个比特位 画图的深度值 (前后顺序的层)
EGL_NONE //这个机构结束了
};
EGLint format(0);
EGLint numConfigs(0);
//让EGL为你选择一个配置
eglChooseConfig(_display, attribs, &_config, 1, &numConfigs);
//可以查询某个配置的某个属性
eglGetConfigAttrib(_display, _config, EGL_NATIVE_VISUAL_ID, &format);
//4:创建 Surface
_surface = eglCreateWindowSurface(_display, _config, _hWnd, NULL);
//5:创建上下文对象
EGLint attr[] ={ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };
//创建上下文对象
EGLContext _context = eglCreateContext(_display, _config, EGL_NO_CONTEXT, attr);
//6:查看 Display Surface Context 是否创建成功
if (eglMakeCurrent(_display, _surface, _surface, _context) == EGL_FALSE){
return false;
}
//查询Suface的属性 获取Suface中的宽高
eglQuerySurface(_display, _surface, EGL_WIDTH, &_width);
eglQuerySurface(_display, _surface, EGL_HEIGHT, &_height);
return true;
}
bool ini(){
if(!glInit()){return false;}
shader.shaderInit();
return true;
}
void renderer(){
//GL_DEPTH_BUFFER_BIT 深度缓冲区
//GL_STENCIL_BUFFER_BIT 模版缓冲区
//GL_COLOR_BUFFER_BIT 颜色缓冲区
//清楚缓冲
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//设置视口的大小
glViewport(0,0,_width,_height);
CELL::matrix4 project=CELL::ortho<float>(0,(float)_width,(float)_height,0,-100,100);
//CELL::matrix4 project=CELL::lookAt(CELL::float3(0,0,5),CELL::float3(0,0,0),CELL::float3(0,1,0));
shader.begin();
float x=100;
float y=200;
float w=50;
float h=50;
//逆时针给坐标点,顺时针会出问题
CELL::float2 pos[]={
CELL::float2(x,y),
CELL::float2(x,y+h),
CELL::float2(x+w,y),
CELL::float2(x+w,y+h)
};
/** 给Uniform变量赋值
* @param location 变量
* @param count 值数量(当前数据里面有几个值 1,2,3,4)
* @param transpose 是否转置(true,false)
* @param value 赋值数据
*/
glUniformMatrix4fv(shader._MVP,1,false,project.data());
//给Uniform变量赋值
glUniform4f(shader._color,1,0,0,1);
/** 设置顶点属性
* @param indx 属性id
* @param size 值数量(2,3,4)
* @param type 数据类型 (GL_UNSIGNED_BYTE,GL_FLOAT...)
* @param normalized 规格化(false,true)
* @param stride 偏移量(数据的偏移量)
* @param ptr 数据
*/
glVertexAttribPointer(shader._position,2,GL_FLOAT,false,sizeof(CELL::float2),pos);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
shader.end();
eglSwapBuffers(_display,_surface);
}
};
运行结果
源码下载地址 (不是完整工程,只有用到的工程文件)
http://pan.baidu.com/s/1geVargZ rect.zip(源码工程)
完整工程
http://pan.baidu.com/s/1geVargZ OpenGL_ES.zip(源码工程)
-- 画东西的几种类型
#define GL_POINTS 点 n/2个点,n是点数
#define GL_LINES 线(两个点确定一条线,点的数据必须是2的整数倍)
#define GL_LINE_STRIP 线带,
首尾不相连接(线带,假如有3个点:第1个的点和第2个点的相连,第2个点和第3条线,第3个点不和第1个点连接->首尾不相连接)
#define GL_LINE_LOOP 线环,首尾相连(线环,假如有3个点:第1个的点和第2个点的相连,第2个点和第3条线,第3个点和第1个点连接->首尾连接)
#define GL_TRIANGLES 三角形 (三个点画一个三角形,点的数据必须是3的整数倍)
#define GL_TRIANGLE_STRIP 三角形带, n-2个三角形,n是点数 (假如有4个点,可以画2个三角形,前三个点是一个三角形,后一个点和离它近的两个点组成一个三角形)
#define GL_TRIANGLE_FAN 三角形扇 (例画圆,圆心是一点,圆周长上一点,在圆周长上一点,在圆周长上一点,...
前三个点是一个三角形,后一个周长上的点和圆心点和上一个周长上的一点又组成一个三角形...
画n个三角形组成一个圆)
/*** 绘制数组
* @param mode 绘画的模式(点,线,三角形)
* @param first 顶点数组 第几个开始
* @param count 顶点数组 大小
*/
GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
/**绘制元素
* @param mode 绘制模式(GL_TRIANGLES三角形...)
* @param count 绘制数据大小(绘制多少个点)
* @param type 数据类型(GL_UNSIGNED_BYTE ...)
* @param indices
* 0:顶点缓冲和索引缓冲数据都用
* indexBuf:用顶点缓冲区数据不要索引缓冲区数据,就把索引数据传入
* @return
*/
GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
引用Shader中的属性(自己在Shader中写的一些需要传值的类型) glGetU/A...
类似这样
typedef int attribute;
attribute _position;
const char* vs = {
...
"attribute vec2 _position;"
...
};
_position = glGetAttribLocation(shaderveual._programId, "_position");
设置Shader数据(Shader什么类型就用什么类型设置内容) glU/V...
类似这样
//逆时针给坐标点,顺时针会出问题
CELL::float2 pos[]={
CELL::float2(x,y),
CELL::float2(x,y+h),
CELL::float2(x+w,y),
CELL::float2(x+w,y+h)
};
...
glVertexAttribPointer(shader._position,2,GL_FLOAT,false,sizeof(CELL::float2),pos);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
...
以上是关于OpenGLES---画一个矩形的主要内容,如果未能解决你的问题,请参考以下文章
OpenglES2.0 for Android:来画个矩形吧