学习使用GLES,首先要写着色器。
与OpenGL ES1.x渲染管线相比,OpenGL ES 2.0渲染管线中“顶点着色器”取代了OpenGL ES 1.x渲染管线中的“变换和光照”;“片元着色器”取代了OpenGL ES 1.x渲染管线中的“纹理环境和颜色求和”、“雾”以及“Alpha测试”。
以上内容转载自:
http://blog.sina.com.cn/s/blog_923fdd9b0102vbe0.html
文章对着色器做了一些介绍,在GLES的使用步骤为:glCreateProgram->glAttachShader->glLinkProgram->glUseProgram。在之后使用纹理之后才知道,一个程序里可能同时存在多个program,在绘制不同对象时需要切换使用glUseProgram。在出现错误的时候错误日志非常关键,调试的时候发现同样的shader代码在windows平台可以绘制,但是在ubuntu中就无法显示,错误日志可能提示语言的版本不支持。这些错误与系统GPU有关系。以下为包含着色器的Program封装,包括常规程序和带纹理的程序。
#pragma once
// 矩阵操作
#include <math.h>
#include "glm/mat4x4.hpp"
#include "glm/ext.hpp"
class ShaderId
{
public:
ShaderId()
{
_shaderId = -1;
}
int _shaderId;
};
class ProgramId
{
public:
int _programId;
ShaderId _vertex;
ShaderId _fragment;
public:
ProgramId()
{
_programId = -1;
}
public:
/**
* 加载函数
*/
virtual bool createProgram(const char* vertex, const char* fragment)
{
#ifndef ANDROID
glewInit(); // android need of not?
#endif
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);
GLUtil::instance()->outputString(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);
GLUtil::instance()->outputString(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);
GLUtil::instance()->outputString(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(const glm::mat4& mat)
{
glUseProgram(_programId);
glm::mat4 matTemp = mat;// *m_view/* * module*/;
GLfloat *mvp = (GLfloat*)glm::value_ptr(matTemp);
glUniformMatrix4fv(this->mvp(), 1, GL_FALSE, mvp);
}
virtual void end()
{
glUseProgram(0);
}
virtual bool initialize(){ return false; }
virtual GLint position() { return -1; }
virtual GLint color() { return -1; }
virtual GLint texure() { return -1; }
virtual GLint mvp() { return -1; }
virtual GLint uv() { return -1; }
};
class PROGRAM_P2_AC4 :public ProgramId
{
public:
typedef int attribute;
typedef int uniform;
protected:
attribute _position;
attribute _color;
uniform _MVP;
public:
virtual GLint position() { return _position; }
virtual GLint color() { return _color; }
virtual GLint texure() { return -1; }
virtual GLint mvp() { return _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 vec3 _position;"
"attribute vec4 _color;"
"varying vec4 _outColor;"
"void main()"
"{"
" vec4 pos = vec4(_position, 1.);"
" _outColor = _color;"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"precision lowp float; "
"varying vec4 _outColor;"
"void main()"
"{"
" gl_FragColor = _outColor;"
"}"
};
*/
#ifdef ANDROID
const char* vs =
{
"attribute vec3 _position;"
"attribute vec4 _color;"
"varying vec4 _outColor;"
"uniform mat4 _MVP;"
"void main()"
"{"
" vec4 pos = vec4(_position, 1.);"
" _outColor = _color;"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"precision mediump float;"
"varying vec4 _outColor;"
"void main()"
"{"
" gl_FragColor = _outColor;"
"}"
};
#else
const char* vs =
{
"#version 130\n"
"in vec3 _position;"
"in vec4 _color;"
"out vec4 _outColor;"
"uniform mat4 _MVP;"
"void main()"
"{"
" vec4 pos = vec4(_position, 1.);"
" _outColor = _color;"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"#version 130\n"
"in vec4 _outColor;"
"out vec4 FragColor;"
"void main()"
"{"
" FragColor = _outColor;"
"}"
};
#endif
bool res = createProgram(vs, ps);
if (res)
{
_position = glGetAttribLocation(_programId, "_position");
_color = glGetAttribLocation(_programId, "_color");
_MVP = glGetUniformLocation(_programId, "_MVP");
}
return res;
}
/**
* 使用程序
*/
virtual void begin(const glm::mat4& mat)
{
ProgramId::begin(mat);
glEnableVertexAttribArray(_position);
glEnableVertexAttribArray(_color);
}
/**
* 使用完成
*/
virtual void end()
{
glDisableVertexAttribArray(_position);
glDisableVertexAttribArray(_color);
glUseProgram(0);
}
};
class PROGRAM_P2_UV_AC4 :public PROGRAM_P2_AC4
{
public:
typedef int attribute;
typedef int uniform;
protected:
//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 GLint uv() { return _uv; }
virtual GLint texure() { return _texture; }
/// 初始化函数
virtual bool initialize()
{
#ifdef ANDROID
const char* vs =
{
"precision lowp float; "
"uniform mat4 _MVP;"
"attribute vec3 _position;"
"attribute vec2 _uv;"
"attribute vec4 _color;"
"varying vec4 _outColor;"
"varying vec2 _outUV;"
"void main()"
"{"
" vec4 pos = vec4(_position, 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"
"}"
};
#else
const char* vs =
{
"#version 130\n"
"in vec3 _position;"
"in vec2 _uv;"
"in vec4 _color;"
"out vec4 _outColor;"
"out vec2 _outUV;"
"uniform mat4 _MVP;"
"void main()"
"{"
" vec4 pos = vec4(_position, 1.);"
" _outColor = _color;"
" _outUV = _uv;"
" gl_Position = _MVP * pos;"
"}"
};
const char* ps =
{
"#version 130\n"
"uniform sampler2D _texture;"
"in vec4 _outColor;"
"in vec2 _outUV;"
"out vec4 FragColor;"
"void main()"
"{"
" vec4 tColor = texture2D(_texture,_outUV);\n"
" FragColor = tColor * _outColor;"
"}"
};
#endif
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(const glm::mat4& mat)
{
ProgramId::begin(mat);
glEnableVertexAttribArray(_position);
glEnableVertexAttribArray(_uv);
glEnableVertexAttribArray(_color);
}
/**
* 使用完成
*/
virtual void end()
{
glDisableVertexAttribArray(_position);
glDisableVertexAttribArray(_uv);
glDisableVertexAttribArray(_color);
glUseProgram(0);
}
};
代码编写参考了:
http://blog.youkuaiyun.com/hb707934728/article/details/71486631?locationNum=4&fps=1
主要做的改动:
(1)着色语言,区分android,区分版本,区分坐标——尤其是z坐标引入保证深度测试能够生效(vec4 pos = vec4(_position, 1.););
(2)纹理程序继承自常规程序而非基础程序类;
(3)引入了变换矩阵(用于旋转缩放平移等运算);