OpenGLES—拾取
Posted GameCocos2dx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGLES—拾取相关的知识,希望对你有一定的参考价值。
本人学的OpenGL ES 都是从http://edu.csdn.net/lecturer/440 地方学的!喜欢的支持一下
{拾取
1:给碰撞的物体整个盒子-->包围盒AxisAlignedBox(别名aabb)
2:用射线与盒子相交 ray.intersects(盒子)
3:加过程
}
1:给碰撞的物体整个盒子-->包围盒AxisAlignedBox(别名aabb)
//轴向包围盒
template<typename T>
class AxisAlignedBox
{
public:
enum Extent
{
EXTENT_NULL,//是否被初始化
EXTENT_FINITE,//有限大
EXTENT_INFINITE//无限大
};
public:
tvec3<T> _minimum;//最小值
tvec3<T> _maximum;//最大值
Extent _extent;//扩展变量
public:
/*
1-----2
/| /|
/ | / |
5-----4 |
| 0--|--3
| / | /
|/ |/
6-----7
*/
typedef enum
{
FAR_LEFT_BOTTOM = 0,
FAR_LEFT_TOP = 1,
FAR_RIGHT_TOP = 2,
FAR_RIGHT_BOTTOM = 3,
NEAR_RIGHT_BOTTOM = 7,
NEAR_LEFT_BOTTOM = 6,
NEAR_LEFT_TOP = 5,
NEAR_RIGHT_TOP = 4
} CornerEnum;
AxisAlignedBox()
{
_minimum = tvec3<T>( T(-0.5), T(-0.5), T(-0.5) );
_maximum = tvec3<T>( T(0.5), T(0.5), T(0.5) );
_extent = EXTENT_NULL;
}
AxisAlignedBox(const AxisAlignedBox & rkBox)
{
setExtents( rkBox._minimum, rkBox._maximum );
_extent = rkBox._extent;
}
AxisAlignedBox( const tvec3<T>& min, const tvec3<T>& max )
{
setExtents( min, max );
}
AxisAlignedBox(T mx, T my, T mz, T Mx, T My, T Mz )
{
setExtents( mx, my, mz, Mx, My, Mz );
}
AxisAlignedBox<T>& operator=(const AxisAlignedBox<T>& right)
{
setExtents(right._minimum, right._maximum);
return *this;
}
~AxisAlignedBox(){}
//设置/获取最小值
void setMinimum(const tvec3<T>& mins) { _minimum = mins; }
void setMinimum(T x,T y, T z){ _minimum = tvec3<T>(x,y,z); }
const tvec3<T>& getMinimum(void) const { return _minimum; }
tvec3<T>& getMinimum(void) { return _minimum; }
//设置/获取最大值
const tvec3<T>& getMaximum(void) const{ return _maximum; }
tvec3<T>& getMaximum(void) { return _maximum; }
void setMaximum( const tvec3<T>& vec ){
_maximum = vec;
}
void setMaximum( T x, T y, T z ){
_maximum.x = x;
_maximum.y = y;
_maximum.z = z;
}
void setMaximumX( T x ){_maximum.x = x;}
void setMaximumY( T y ){_maximum.y = y;}
void setMaximumZ( T z ){_maximum.z = z;}
/** 设置包围盒大小
* @param min 最小值
* @param max 最大值
*/
void setExtents( const tvec3<T>& min, const tvec3<T>& max ) {
_minimum = min;
_maximum = max;
_extent = EXTENT_FINITE;
}
/** 设置包围盒大小
* @param mx my mz 最小值xyz
* @param Mx My Mz 最大值xyz
*/
void setExtents(T mx, T my, T mz, T Mx, T My, T Mz ){
_minimum.x = mx;
_minimum.y = my;
_minimum.z = mz;
_maximum.x = Mx;
_maximum.y = My;
_maximum.z = Mz;
_extent = EXTENT_FINITE;
}
/** 获取包围盒8个顶点的坐标
Returns a pointer to an array of 8 corner points, useful for
collision vs. non-aligned objects.
@remarks
If the order of these corners is important, they are as
follows: The 4 points of the minimum Z face (note that
because Ogre uses right-handed coordinates, the minimum Z is
at the 'back' of the box) starting with the minimum point of
all, then anticlockwise around this face (if you are looking
onto the face from outside the box). Then the 4 points of the
maximum Z face, starting with maximum point of all, then
anticlockwise around this face (looking onto the face from
outside the box). Like this:
<pre>
1-----2
/| /|
/ | / |
5-----4 |
| 0--|--3
| / | /
|/ |/
6-----7
</pre>
@remarks as this implementation uses a static member, make sure to use your own copy !
*/
void getAllCorners(tvec3<T> mpCorners[8] ) const {
mpCorners[0] = _minimum;
mpCorners[1].x = _minimum.x; mpCorners[1].y = _maximum.y; mpCorners[1].z = _minimum.z;
mpCorners[2].x = _maximum.x; mpCorners[2].y = _maximum.y; mpCorners[2].z = _minimum.z;
mpCorners[3].x = _maximum.x; mpCorners[3].y = _minimum.y; mpCorners[3].z = _minimum.z;
mpCorners[4] = _maximum;
mpCorners[5].x = _minimum.x; mpCorners[5].y = _maximum.y; mpCorners[5].z = _maximum.z;
mpCorners[6].x = _minimum.x; mpCorners[6].y = _minimum.y; mpCorners[6].z = _maximum.z;
mpCorners[7].x = _maximum.x; mpCorners[7].y = _minimum.y; mpCorners[7].z = _maximum.z;
}
/** 获取局部顶点
* @param cornerToGet 方向枚举值
* gets the position of one of the corners
*/
tvec3<T> getCorner(CornerEnum cornerToGet) const
{
switch(cornerToGet)
{
case FAR_LEFT_BOTTOM:
return _minimum;
case FAR_LEFT_TOP:
return tvec3<T>(_minimum.x, _maximum.y, _minimum.z);
case FAR_RIGHT_TOP:
return tvec3<T>(_maximum.x, _maximum.y, _minimum.z);
case FAR_RIGHT_BOTTOM:
return tvec3<T>(_maximum.x, _minimum.y, _minimum.z);
case NEAR_RIGHT_BOTTOM:
return tvec3<T>(_maximum.x, _minimum.y, _maximum.z);
case NEAR_LEFT_BOTTOM:
return tvec3<T>(_minimum.x, _minimum.y, _maximum.z);
case NEAR_LEFT_TOP:
return tvec3<T>(_minimum.x, _maximum.y, _maximum.z);
case NEAR_RIGHT_TOP:
return _maximum;
default:
return tvec3<T>();
}
}
/** 合并包围盒
* 两个包围盒合到一起,就是取并集
* Merges the passed in box into the current box. The result is the
* box which encompasses both.
*/
void merge( const AxisAlignedBox<T>& right )
{
if ((right._extent == EXTENT_NULL) || (_extent == EXTENT_INFINITE)){
return;
}else if (right._extent == EXTENT_INFINITE){
_extent = EXTENT_INFINITE;
}else if (_extent == EXTENT_NULL){
setExtents(right._minimum, right._maximum);
}else{
//! merge
tvec3<T> min = _minimum;
tvec3<T> max = _maximum;
max.makeCeil(right._maximum);//取最大值
min.makeFloor(right._minimum);//取最小值
setExtents(min, max);
}
}
/**
* Extends the box to encompass the specified point (if needed).
*/
void merge( const tvec3<T>& point )
{
switch (_extent)
{
case EXTENT_NULL: // if null, use this point
setExtents(point, point);
return;
case EXTENT_FINITE:
_maximum.makeCeil(point);
_minimum.makeFloor(point);
return;
case EXTENT_INFINITE:
return;
}
}
/*** 模型变换了,从新计算最大值/最小值
* 正方形6个面一共36顶点,在算出最大值和最小值,在和模型相乘
* 原理:8个顶点和矩阵相乘,得到新的8个顶点,在求最大值和最小值
* @param matrix 模型矩阵
*/
void transform( const tmat4x4<T>& matrix )
{
tvec3<T> oldMin;
tvec3<T> oldMax;
tvec3<T> currentCorner;
oldMin = _minimum;
oldMax = _maximum;
// We sequentially compute the corners in the following order :
// 0, 6, 5, 1, 2, 4 ,7 , 3
// This sequence allows us to only change one member at a time to get at all corners.
// For each one, we transform it using the matrix
// Which gives the resulting point and merge the resulting point.
currentCorner = oldMin;
tvec3<T> vVert = currentCorner * matrix;
setExtents(vVert,vVert);
// First corner
// min min min
currentCorner = oldMin;
merge( currentCorner * matrix );
// min,min,max
currentCorner.z = oldMax.z;
merge( currentCorner * matrix );
// min max max
currentCorner.y = oldMax.y;
merge( currentCorner * matrix );
// min max min
currentCorner.z = oldMin.z;
merge( currentCorner * matrix );
// max max min
currentCorner.x = oldMax.x;
merge( currentCorner * matrix );
// max max max
currentCorner.z = oldMax.z;
merge( currentCorner * matrix );
// max min max
currentCorner.y = oldMin.y;
merge( currentCorner * matrix);
// max min min
currentCorner.z = oldMin.z;
merge( currentCorner * matrix);
}
/** 和盒子相交(两个盒子相交)
* Returns whether or not this box intersects another.
* @param b2 第二个盒子
* @return true 相交,false 不相交
*/
bool intersects(const AxisAlignedBox& b2) const
{
if (_maximum.x < b2._minimum.x)
return false;
if (_maximum.y < b2._minimum.y)
return false;
if (_maximum.z < b2._minimum.z)
return false;
if (_minimum.x > b2._maximum.x)
return false;
if (_minimum.y > b2._maximum.y)
return false;
if (_minimum.z > b2._maximum.z)
return false;
return true;
}
/** 和盒子相交(两个盒子相交),不考虑z轴
* Returns whether or not this box intersects another.
* @param b2 第二个盒子
* @return true 相交,false 不相交
*/
bool intersectsNoZ(const AxisAlignedBox& b2) const
{
if (_maximum.x < b2._minimum.x)
return false;
if (_maximum.y < b2._minimum.y)
return false;
if (_minimum.x > b2._maximum.x)
return false;
if (_minimum.y > b2._maximum.y)
return false;
return true;
}
/** 和盒子相交(两个盒子相交)
* Returns whether or not this box intersects another.
* @param b2 第二个盒子
* @return 返回交集
*/
AxisAlignedBox<T> intersection(const AxisAlignedBox<T>& b2) const
{
tvec3<T> intMin = _minimum;
tvec3<T> intMax = _maximum;
intMin.makeCeil(b2.getMinimum());
intMax.makeFloor(b2.getMaximum());
if (intMin.x < intMax.x && intMin.y < intMax.y &&intMin.z < intMax.z){
return AxisAlignedBox<T>(intMin, intMax);
}
return AxisAlignedBox<T>();
}
//是否被初始化
bool isNull(void) const {return (_extent == EXTENT_NULL); }
void setNull() {_extent = EXTENT_NULL; }
//是否是有限的
bool isFinite(void) const{ return (_extent == EXTENT_FINITE);}
void setInfinite() {_extent = EXTENT_INFINITE; }
bool isInfinite(void) const
{
return (_extent == EXTENT_INFINITE);
}
//缩放
void scale(const tvec3<T>& s){
tvec3<T> min = _minimum * s;
tvec3<T> max = _maximum * s;
setExtents(min, max);
}
/*** 和点相交
* @param v 三维点
*/
bool intersects(const tvec3<T>& v) const
{
return( v.x >= _minimum.x && v.x <= _maximum.x &&
v.y >= _minimum.y && v.y <= _maximum.y &&
v.z >= _minimum.z && v.z <= _maximum.z);
}
/*** 和点相交
* @param v 二维点
*/
bool intersects(const tvec2<T>& v) const
{
return( v.x >= _minimum.x && v.x <= _maximum.x &&
v.y >= _minimum.y && v.y <= _maximum.y );
}
//获取包围盒中心点
tvec3<T> getCenter(void) const
{
return tvec3<T>(
(_maximum.x + _minimum.x) * T(0.5f),
(_maximum.y + _minimum.y) * T(0.5f),
(_maximum.z + _minimum.z) * T(0.5f)
);
}
//获取包围盒大小
tvec3<T> getSize(void) const { return _maximum - _minimum; }
//获取包围盒一半的大小
tvec3<T> getHalfSize(void) const { return (_maximum - _minimum) * T(0.5); }
//是否包含点
bool contains(const tvec3<T>& v) const
{
return _minimum.x <= v.x && v.x <= _maximum.x &&
_minimum.y <= v.y && v.y <= _maximum.y &&
_minimum.z <= v.z && v.z <= _maximum.z;
}
//是否包含盒子
bool contains(const AxisAlignedBox& other) const
{
return this->_minimum.x <= other._minimum.x &&
this->_minimum.y <= other._minimum.y &&
this->_minimum.z <= other._minimum.z &&
other._maximum.x <= this->_maximum.x &&
other._maximum.y <= this->_maximum.y &&
other._maximum.z <= this->_maximum.z;
}
bool operator== (const AxisAlignedBox& right) const
{
return this->_minimum == right._minimum &&
this->_maximum == right._maximum;
}
bool operator!= (const AxisAlignedBox& right) const
{
return !(*this == right);
}
};
2:用射线与盒子相交 ray.intersects(盒子)
//射线
template<typename T>
class tray
{
typedef T value_type;
typedef tray<T> type;
protected:
tvec3<T> _origin;//起始点
tvec3<T> _direction;//方向
public:
tray():
_origin(value_type(0),value_type(0),value_type(0)),
_direction(value_type(0),value_type(0),value_type(1))
{}
tray(const tvec3<T>& origin, const tvec3<T>& direction):
_origin(origin),
_direction(direction)
{}
//设置射线的起点
void setOrigin(const tvec3<T>& origin) { _origin = origin; }
// 返回射线的起点
const tvec3<T>& getOrigin(void) const{ return _origin; }
//设置射线的方向
void setDirection(const tvec3<T>& dir) { _direction = dir; }
//返回射线的方向
const tvec3<T>& getDirection(void) const { return _direction; }
/**
* Gets the position of a point t units along the ray.
*/
tvec3<T> getPoint(T time) const { return tvec3<T>(_origin + (_direction * time));}
/** 射线与box相交
* 如果相交,返回值中的first == true.否则false
* second为射线到点的距离
* 调用getPoint方法,则返回交点
* @param box 盒子
* @return std::pair<bool, T>.first 是否碰上,true碰上,false没有碰上
* @return std::pair<bool, T>.second 射线到点的距离(这是个时间), getPoint(pair.second)得到交点
*/
std::pair<bool, T> intersects(const AxisAlignedBox<T>& box) const
{
T lowt = 0.0f;
T t;
bool hit = false;
tvec3<T> hitpoint;
tvec3<T> min = box.getMinimum();
tvec3<T> max = box.getMaximum();
// 点在包围盒里面
if ( _origin > min && _origin < max )
{
return std::pair<bool, T>(true, 0);
}
// Check each face in turn, only check closest 3
// Min x
if (_origin.x <= min.x && _direction.x > 0)
{
t = (min.x - _origin.x) / _direction.x;
if (t >= 0)
{
// Substitute t back into ray and check bounds and dist
hitpoint = _origin + _direction * t;
if (hitpoint.y >= min.y &&
hitpoint.y <= max.y &&
hitpoint.z >= min.z &&
hitpoint.z <= max.z &&
(!hit || t < lowt))
{
hit = true;
lowt = t;
}
}
}
// Max x
if (_origin.x >= max.x && _direction.x < 0)
{
t = (max.x - _origin.x) / _direction.x;
if (t >= 0)
{
// Substitute t back into ray and check bounds and dist
hitpoint = _origin + _direction * t;
if (hitpoint.y >= min.y &&
hitpoint.y <= max.y &&
hitpoint.z >= min.z &&
hitpoint.z <= max.z &&
(!hit || t < lowt))
{
hit = true;
lowt = t;
}
}
}
// Min y
if (_origin.y <= min.y && _direction.y > 0)
{
t = (min.y - _origin.y) / _direction.y;
if (t >= 0)
{
// Substitute t back into ray and check bounds and dist
hitpoint = _origin + _direction * t;
if (hitpoint.x >= min.x &&
hitpoint.x <= max.x &&
hitpoint.z >= min.z &&
hitpoint.z <= max.z &&
(!hit || t < lowt))
{
hit = true;
lowt = t;
}
}
}
// Max y
if (_origin.y >= max.y && _direction.y < 0)
{
t = (max.y - _origin.y) / _direction.y;
if (t >= 0)
{
// Substitute t back into ray and check bounds and dist
hitpoint = _origin + _direction * t;
if (hitpoint.x >= min.x &&
hitpoint.x <= max.x &&
hitpoint.z >= min.z &&
hitpoint.z <= max.z &&
(!hit || t < lowt))
{
hit = true;
lowt = t;
}
}
}
// Min z
if (_origin.z <= min.z && _direction.z > 0)
{
t = (min.z - _origin.z) / _direction.z;
if (t >= 0)
{
// Substitute t back into ray and check bounds and dist
hitpoint = _origin + _direction * t;
if (hitpoint.x >= min.x &&
hitpoint.x <= max.x &&
hitpoint.y >= min.y &&
hitpoint.y <= max.y &&
(!hit || t < lowt))
{
hit = true;
lowt = t;
}
}
}
// Max z
if (_origin.z >= max.z && _direction.z < 0)
{
t = (max.z - _origin.z) / _direction.z;
if (t >= 0)
{
// Substitute t back into ray and check bounds and dist
hitpoint = _origin + _direction * t;
if (hitpoint.x >= min.x &&
hitpoint.x <= max.x &&
hitpoint.y >= min.y &&
hitpoint.y <= max.y &&
(!hit || t < lowt))
{
hit = true;
lowt = t;
}
}
}
return std::pair<bool, T>(hit, lowt);
}
};
template<typename T>
/*** 射线与三角形相交
* @param orig 射线原点
* @param dir 射线方向
* @param v0, v1, v2 三角形三个点
* @param t 返回的时间
* @param u,v 返回各个方向的一个分量
*/
bool intersectTriangle( const tvec3<T>& orig,const tvec3<T>& dir,tvec3<T>& v0, tvec3<T>& v1,tvec3<T>& v2, T* t, T* u, T* v )
{
// Find vectors for two edges sharing vert0
tvec3<T> edge1 = v1 - v0;
tvec3<T> edge2 = v2 - v0;
// Begin calculating determinant - also used to calculate U parameter
tvec3<T> pvec;
pvec = cross(dir, edge2 );
// If determinant is near zero, ray lies in plane of triangle
T det = dot( edge1,pvec );
tvec3<T> tvec;
if( det > 0 )
{
tvec = orig - v0;
}
else
{
tvec = v0 - orig;
det = -det;
}
if( det < 0.0001f )
return false;
// Calculate U parameter and test bounds
*u = dot( tvec, pvec );
if( *u < 0.0f || *u > det )
return false;
// Prepare to test V parameter
tvec3<T> qvec;
qvec = cross(tvec, edge1 );
// Calculate V parameter and test bounds
*v = dot( dir, qvec );
if( *v < T(0.0f) || *u + *v > det )
return false;
*t = dot( edge2,qvec );
T fInvDet = T(1.0) / det;
*t *= fInvDet;
*u *= fInvDet;
*v *= fInvDet;
return true;
}
3:加过程
typedef AxisAlignedBox<float> aabb3d;
typedef tray<float> Ray;
{初始化变量
AABBVertex ptLine[2];//射线的两个点(画射线用)
CELL::aabb3d aabbBox;//包围盒
CELL::aabb3d aabbTran;//记录aabbBox包围盒(包围盒改变后的大小,也是更新的大小)
CELL::float3 vMin=(FLT_MAX,FLT_MAX,FLT_MAX);
CELL::float3 vMax=(-FLT_MAX,-FLT_MAX,-FLT_MAX);
//aabbBoxVertex 要添加盒子的模型数据
size_t count=sizeof(aabbBoxVertex)/sizeof(aabbBoxVertex[0]);//正方形6个面,每个面6个顶点(两个三角形组成一个面)一共36顶点
for (size_t i=0;i<count;i++){
vMin.x=min(aabbBoxVertex[i].x,vMin.x);
vMin.y=min(aabbBoxVertex[i].y,vMin.y);
vMin.z=min(aabbBoxVertex[i].z,vMin.z);
vMax.x=max(aabbBoxVertex[i].x,vMax.x);
vMax.y=max(aabbBoxVertex[i].y,vMax.y);
vMax.z=max(aabbBoxVertex[i].z,vMax.z);
}
aabbBox.setExtents(vMin,vMax);
}
{鼠标交互
virtual void onMousePress(int absx, int absy, MouseKeyCode id) {
if(id==MouseKeyCode::Left) {
CELL::Ray ray=camera.createRayFromScreen(absx,absy);//得到射线
CELL::float3 post=ray.getOrigin();//射线起始点的位置
float tm=(post.y)/ray.getDirection().y;
//得到地面的焦点位置
//CELL::float3 target= dd.getPoint(abs(tm));
CELL::float3 target= ray.getOrigin()+ray.getDirection()*abs(tm);
target=CELL::float3(target.x,0,target.z);
//设置物体移动到什么位置
role.setTarget(target);
{//画射线(获取点)
ptLine[0].x=post.x;//起始点
ptLine[0].y=post.y;
ptLine[0].z=post.z;
ptLine[1].x=target.x;//终点(目标点)
ptLine[1].y=target.y;
ptLine[1].z=target.z;
}
std::pair<bool, float> parl=ray.intersects(aabbTran);//射线与box相交
//intersectTriangle();射线与三角形相交
static int index=0;
if(parl.first){
CELL::float3 jd=ray.getPoint(parl.second);
printf("碰撞上了 %d --> 焦点(%f,%f,%f)\\n",++index,jd.x,jd.y,jd.z);
}
}else if(id==MouseKeyCode::Right){
mousePos=CELL::float2(absx,absy);
isRight=true;
}
}
}
{画
{//画射线
glLineWidth(5);
glVertexAttribPointer(shader._positionAttr, 3, GL_FLOAT,false,sizeof(AABBVertex),&ptLine[0].x);
glVertexAttribPointer(shader._uvAttr, 2, GL_FLOAT,false,sizeof(AABBVertex),&ptLine[0].u);
glVertexAttribPointer(shader._colorAttr, 4, GL_FLOAT,false,sizeof(AABBVertex),&ptLine[0].r);
glDrawArrays(GL_LINES,0,2);
}
{//移动的立方盒
glBindTexture(GL_TEXTURE_2D,textureRole);
CELL::matrix4 matRot(1);
CELL::matrix4 matModel;
static float agle = 0.0f; agle += 1.0f;
matRot.rotateYXZ(agle,agle,agle);
matModel.translate(role._pos);
aabbTran = aabbBox;
aabbTran.transform(matModel * matRot);
CELL::matrix4 ddz= matModel * matRot;
MVP = matProj * matView * ddz;
glUniformMatrix4fv(shader._MVP,1,false,MVP.data());
glVertexAttribPointer(shader._positionAttr, 3, GL_FLOAT,false,sizeof(AABBVertex),&aabbBoxVertex[0].x);
glVertexAttribPointer(shader._uvAttr, 2, GL_FLOAT,false,sizeof(AABBVertex),&aabbBoxVertex[0].u);
glVertexAttribPointer(shader._colorAttr, 4, GL_FLOAT,false,sizeof(AABBVertex),&aabbBoxVertex[0].r);
glDrawArrays(GL_TRIANGLES,0,sizeof(aabbBoxVertex)/sizeof(aabbBoxVertex[0]));
}
{//画包围盒
CELL::float3 arBox[8];
AABBVertex vertexBox[8];
aabbTran.getAllCorners(arBox);
for (size_t i = 0 ; i < 8 ;++ i ){//顶点位置
vertexBox[i].x = arBox[i].x;
vertexBox[i].y = arBox[i].y;
vertexBox[i].z = arBox[i].z;
}
short boxIndex[24] = {//索引--必须按照返回的vertexBox数组设置,具体看这个函数getAllCorners
0,1,2,3,//后
2,3,7,4,//右
4,5,6,7,//前
1,0,6,5,//左
2,4,5,1,//上
0,3,7,6//下
};
MVP = matProj * matView;
glUniformMatrix4fv(shader._MVP,1,false,MVP.data());
glVertexAttribPointer(shader._positionAttr, 3, GL_FLOAT,false,sizeof(AABBVertex),&vertexBox[0].x);
size_t count=sizeof(boxIndex)/sizeof(boxIndex[0]);
for (size_t i=0;i<count;i+=4){
glDrawElements(GL_LINE_STRIP,4,GL_UNSIGNED_SHORT, &boxIndex[i]);
}
}
}
{Shader
const char vs[]={
"uniform mat4 _MVP;"
"attribute vec3 _positionAttr;"
"attribute vec4 _colorAttr;"
"attribute vec2 _uvAttr;"
"varying vec4 _outColor;"
"varying vec2 _outUV;"
"void main(){"
" vec4 pos = vec4(_positionAttr.x,_positionAttr.y,_positionAttr.z,1);"
" gl_Position = _MVP * pos;"
" _outColor = _colorAttr;"
" _outUV = _uvAttr;"
"}"
};
const char fs[]={
"precision lowp float; "
"uniform sampler2D _texture;"
"varying vec4 _outColor;"
"varying vec2 _outUV;"
"void main()"
"{"
" vec4 color = texture2D(_texture,_outUV);"
" gl_FragColor = color * _outColor;"
"}"
};
pValue=creteShaderProgram(vs,fs);//编译Shader程序
_MVP=glGetUniformLocation(pValue.pID,"_MVP");
_texture=glGetUniformLocation(pValue.pID,"_texture");
_positionAttr=glGetAttribLocation(pValue.pID,"_positionAttr");
_uvAttr=glGetAttribLocation(pValue.pID,"_uvAttr");
_colorAttr=glGetAttribLocation(pValue.pID,"_colorAttr");
}
效果图
文字有点模糊
蓝色的线是--射线
黄色的线是--模型
橙色的线是--包围盒
源码地址 http://pan.baidu.com/s/1geVargZ 拾取.zip
推荐博客
http://www.cnblogs.com/seebro/p/3801597.html
以上是关于OpenGLES—拾取的主要内容,如果未能解决你的问题,请参考以下文章
Android OpenGLES3绘图 - 音频可视化(模仿MIUI系统效果)
用于模糊的 OpenGL ES 2.0 片段着色器速度慢且质量低
我的OpenGL学习进阶之旅OpenGL ES 3.0实现了具有可编程着色功能的图形管线