目录
相关文章
OpenGL系列之一:OpenGL第一个程序
OpenGL系列之二:绘制三角形
OpenGL系列之三:三角形顶点增加颜色
OpenGL系列之四:绘制四边形
OpenGL系列之五:绘制点和线
OpenGL系列之六:绘制立方体
OpenGL系列之七:纹理贴图
实现效果
实现步骤
1.修改渲染器
这里是以之前第七个程序(OpenGL系列之七:纹理贴图)为基础,修改GLRender中的JNI函数ndkLoadGLTexTureID,增加了一个索引(因为需要有六个纹理,因此纹理ID存到了数组里,因此需要用到索引),然后GLRender类修改如下:
class GLRender(val context:Context) : GLSurfaceView.Renderer{
init {
System.loadLibrary("CCOpenGLRender")
}
private external fun ndkInitGL()
private external fun ndkPaintGL()
private external fun ndkResizeGL(width:Int,height:Int)
private external fun ndkLoadGLTexTureID(fileName:String,textTureIndex:Int)
override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {
//初始化
ndkInitGL()
for (i in 0..6){
val file = File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"texture/${i}.png")
if(file.exists()){
Log.e("测试",file.absolutePath)
ndkLoadGLTexTureID(file.absolutePath,i)
}
}
}
override fun onSurfaceChanged(p0: GL10?, p1: Int, p2: Int) {
//改变大小
ndkResizeGL(p1,p2)
}
override fun onDrawFrame(p0: GL10?) {
//绘制
ndkPaintGL()
}
}
onSurfaceCreated中循环加载6张图片
图片如下
2.修改JNI函数
这里我们修改Java_com_itfitness_opengldemo_GLRender_ndkLoadGLTexTureID函数如下:
GLuint m_texID[6];
int width, height, nrChannels;
extern "C"
JNIEXPORT void JNICALL
Java_com_itfitness_opengldemo_GLRender_ndkLoadGLTexTureID(JNIEnv *env, jobject thiz,
jstring file_name,jint texTureIndex) {
glEnable(GL_TEXTURE_2D);
glGenTextures(1,&m_texID[texTureIndex]);//产生纹理索引
glBindTexture(GL_TEXTURE_2D,m_texID[texTureIndex]);//绑定纹理索引,之后的操作都针对当前纹理索引
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//指当纹理图象被使用到一个大于它的形状上时
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//指当纹理图象被使用到一个小于或等于它的形状上时
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
const char* fileName = env->GetStringUTFChars(file_name,0);
// 让图像正过来(如果不加图像是倒过来的)
stbi_set_flip_vertically_on_load(true);
// 加载并生成纹理
unsigned char *data = stbi_load(fileName, &width, &height, &nrChannels, 0);
if (data)
{
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
}
// 释放资源
env->ReleaseStringUTFChars(file_name, fileName);
stbi_image_free(data);
}
主要是增加了索引,然后textureID用数组存储,然后是渲染函数中因为需要绘制立方体因此增加了顶点数量,同时在绘制的时候采用循环的方式,切换textureid来进行绘制:
extern "C"
JNIEXPORT void JNICALL
Java_com_itfitness_opengldemo_GLRender_ndkPaintGL(JNIEnv *env, jobject thiz) {
//清空颜色缓冲区或深度缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//加载模型视图矩阵
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glCullFace(GL_BACK);
//定义立方体顶点
CCFloat5 cubeVert[] = {
{ -0.5f, -0.5f, -0.5f, 0.0f, 0.0f},
{ 0.5f, -0.5f, -0.5f, 1.0f, 0.0f},
{ 0.5f, 0.5f, -0.5f, 1.0f, 1.0f},
{ 0.5f, 0.5f, -0.5f, 1.0f, 1.0f},
{-0.5f, 0.5f, -0.5f, 0.0f, 1.0f},
{-0.5f, -0.5f, -0.5f, 0.0f, 0.0f},
{-0.5f, -0.5f, 0.5f, 0.0f, 0.0f},
{0.5f, -0.5f, 0.5f, 1.0f, 0.0f},
{0.5f, 0.5f, 0.5f, 1.0f, 1.0f},
{0.5f, 0.5f, 0.5f, 1.0f, 1.0f},
{-0.5f, 0.5f, 0.5f, 0.0f, 1.0f},
{-0.5f, -0.5f, 0.5f, 0.0f, 0.0f},
{-0.5f, 0.5f, 0.5f, 1.0f, 0.0f},
{-0.5f, 0.5f, -0.5f, 1.0f, 1.0f},
{-0.5f, -0.5f, -0.5f, 0.0f, 1.0f},
{-0.5f, -0.5f, -0.5f, 0.0f, 1.0f},
{-0.5f, -0.5f, 0.5f, 0.0f, 0.0f},
{-0.5f, 0.5f, 0.5f, 1.0f, 0.0f},
{0.5f, 0.5f, 0.5f, 1.0f, 0.0f},
{0.5f, 0.5f, -0.5f, 1.0f, 1.0f},
{0.5f, -0.5f, -0.5f, 0.0f, 1.0f},
{0.5f, -0.5f, -0.5f, 0.0f, 1.0f},
{0.5f, -0.5f, 0.5f, 0.0f, 0.0f},
{0.5f, 0.5f, 0.5f, 1.0f, 0.0f},
{-0.5f, -0.5f, -0.5f, 0.0f, 1.0f},
{0.5f, -0.5f, -0.5f, 1.0f, 1.0f},
{0.5f, -0.5f, 0.5f, 1.0f, 0.0f},
{0.5f, -0.5f, 0.5f, 1.0f, 0.0f},
{-0.5f, -0.5f, 0.5f, 0.0f, 0.0f},
{-0.5f, -0.5f, -0.5f, 0.0f, 1.0f},
{-0.5f, 0.5f, -0.5f, 0.0f, 1.0f},
{0.5f, 0.5f, -0.5f, 1.0f, 1.0f},
{0.5f, 0.5f, 0.5f, 1.0f, 0.0f},
{0.5f, 0.5f, 0.5f, 1.0f, 0.0f},
{-0.5f, 0.5f, 0.5f, 0.0f, 0.0f},
{-0.5f, 0.5f, -0.5f, 0.0f, 1.0f}
};
//启动一组顶点坐标
glEnableClientState(GL_VERTEX_ARRAY);
//启动TEXTURE
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// 指定绘制的定点数组
// 第一个参数:绘制几个点(这里其实就是CCFloat5中的前三个点x,y,z)
// 第二个参数:类型为float
// 第三个参数:第一个点到第二个点之间的步长(也就是结构体的长度)
// 第四个参数:绘制数据的地址
glVertexPointer(3,GL_FLOAT,sizeof(CCFloat5),cubeVert);
// 指定绘制的定点数组
// 第一个参数:绘制几个点(这里其实就是CCFloat5中的后两个点u,v)
// 第二个参数:类型为float
// 第三个参数:第一个点到第二个点之间的步长(也就是结构体的长度)
// 第四个参数:绘制数据的地址
glTexCoordPointer(2,GL_FLOAT,sizeof(CCFloat5),&cubeVert[0].u);
//旋转起来
m_angle += 0.01f;
glm::mat4x4 cubeMat;
//平移矩阵
glm::mat4x4 cubeTransMat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -0.5));
//旋转矩阵
glm::mat4x4 cubeRotMat = glm::rotate(glm::mat4(1.0f),m_angle,glm::vec3(0.5f, 0.5f, 1.0) );
//缩放矩阵
glm::mat4x4 cubeScaleMat = glm::scale(glm::mat4(1.0f),glm::vec3(0.5f, 0.5f, 0.5) );
cubeMat = cubeTransMat * cubeRotMat * cubeScaleMat;
//加载矩阵
glLoadMatrixf(glm::value_ptr(cubeMat));
//循环绘制六个面
for(int i=0; i< 6; i++)
{
glBindTexture(GL_TEXTURE_2D,m_texID[i]);
glDrawArrays(GL_TRIANGLES,i*6,6);
}
//关闭一组顶点坐标
glDisableClientState(GL_VERTEX_ARRAY);
//关闭TEXTURE
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
案例源码
https://gitee.com/itfitness/opengl-cube-texture.git