【Android OpenGL ES 开发 (三)】Shader 扩展

这篇博客详细介绍了在OpenGL ES环境下如何编译Shader代码,包括顶点Shader和片段Shader,以及如何创建GPU程序。内容涵盖编译Shader接口、生成GPU程序接口的实现,同时讲解了模型矩阵、正交投影在3D与2D绘图中的应用,以及UI元素的绘制和前后关系控制。此外,还涉及到了VBO、IBO的使用以及相关API的封装。
摘要由CSDN通过智能技术生成

编译Shader代码

1.封装一个编译shader的接口

GLuint CompileShader(GLenum shaderType,const char *shaderCode){
    GLuint shader=glCreateShader(shaderType);
    glShaderSource(shader,1,&shaderCode,NULL);
    glCompileShader(shader);
    GLint compileResult=GL_TRUE;
    glGetShaderiv(shader,GL_COMPILE_STATUS,&compileResult);
    if(compileResult==GL_FALSE){
        char szLog[1024]={0};
        GLsizei logLen=0;
        glGetShaderInfoLog(shader,1024,&logLen,szLog);
        __android_log_print(ANDROID_LOG_INFO,"BattleFire","CompileShader %s\n%s\n",szLog,shaderCode);
        glDeleteShader(shader);
        shader=0;
    }
    return shader;
}

2.调用编译shader的接口

    //编译shader
    int filesize=0;
    unsigned char *filecontent=LoadfileContent("test.vs",filesize);
    GLuint vsshader = CompileShader(GL_VERTEX_SHADER,(char*)filecontent);
    delete [] filecontent;
    filecontent=LoadfileContent("test.fs",filesize);
    GLuint fsshader = CompileShader(GL_VERTEX_SHADER,(char*)filecontent);
    delete [] filecontent;

生成GPU程序

1.实现生成GPU程序接口

GLuint CreateProgram(GLuint vs,GLuint fs){
    GLuint program=glCreateProgram();
    glAttachShader(program,vs);
    glAttachShader(program,fs);
    glLinkProgram(program);
    glDetachShader(program,vs);
    glDetachShader(program,fs);
    GLint nResult;
    glGetProgramiv(program,GL_LINK_STATUS,&nResult);
    if(nResult==GL_FALSE){
        char szLog[1024]={0};
        GLsizei logLen=0;
        glGetProgramInfoLog(program,1024,&logLen,szLog);
        __android_log_print(ANDROID_LOG_INFO,"BattleFire","CreateProgram %s\n",szLog);
        glDeleteProgram(program);
        program=0;
    }
    return program;
}

2.编译与生成GPU程序合并封装

GLuint CreateStanarProgram(const char *vertex_shader_path,const char * fragment_shader_path)
{
    //编译shader
    int filesize=0;
    unsigned char *filecontent=LoadfileContent(vertex_shader_path,filesize);
    GLuint vsShade = CompileShader(GL_VERTEX_SHADER,(char*)filecontent);
    delete [] filecontent;
    filecontent=LoadfileContent(fragment_shader_path,filesize);
    GLuint fsShader = CompileShader(GL_VERTEX_SHADER,(char*)filecontent);
    delete [] filecontent;
    GLuint program=CreateProgram(vsShade,fsShader);
    glDeleteShader(vsShade);
    glDeleteShader(fsShader);
    return program;
}

配置好属性组并进行绘制

extern "C" JNIEXPORT void JNICALL
Java_com_example_learnogles_MainActivity_Render(
        JNIEnv* env,
        jobject /* this */) {
    //__android_log_print(ANDROID_LOG_INFO,HANGYU_LOG_TAG,"Render");
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
    glBindBuffer(GL_ARRAY_BUFFER,vbo);//设置状态机
    glUseProgram(program);
    glUniformMatrix4fv(modelMatrixLocation,1,GL_FALSE,glm::value_ptr(modelMatrix));//模型矩阵
    glUniformMatrix4fv(viewMatrixLocation,1,GL_FALSE,glm::value_ptr(viewMatrix));//视口矩阵
    glUniformMatrix4fv(projectionMatrixLocation,1,GL_FALSE,glm::value_ptr(projectionMatrix));//投影矩阵
    //set attribute
    //激活属性组
    glEnableVertexAttribArray(positionLocation);//激活属性位置
    glVertexAttribPointer(positionLocation,4,GL_FLOAT,GL_FALSE,sizeof(Vectice),0);
//    glEnableVertexAttribArray(colorLocation);
//    glVertexAttribPointer(colorLocation,4,GL_FLOAT,GL_FALSE,sizeof(float)*8,(void*)(sizeof(float)*4));

    glDrawArrays(GL_TRIANGLES,0,3);//从第0个点绘制,绘制三个点,会从vbo中取值
    glBindBuffer(GL_ARRAY_BUFFER,0);
    glUseProgram(0);

}

属性在shader间的传递

1.VS

attribute vec4 position;
attribute vec4 color;
uniform mat4 U_ModelMatrix;
uniform mat4 U_ViewMatrix;
uniform mat4 U_ProjectionMatrix;
varying vec4 V_Color;
void main(){
    V_Color=color;
    gl_Position=U_ProjectionMatrix*U_ViewMatrix*U_ModelMatrix*position;
}

2.FS

#ifdef GL_ES
precision mediump float;
#endif
varying vec4 V_Color;
void main(){
    gl_FragColor=V_Color;
}

模型矩阵的使用

1.在世界坐标Z为0的时候,由于平行不能看见任何东西。在这种情况我们可以使用模型矩阵整体平移(原理:是uniform变量,会影响所有点)

//平移
modelMatrix=glm::translate(0.0f,0.0f,-2.0f)
//缩放
glm::scale(0.5f,0.5f,0.5f)
//旋转
glm::rotate(30.0f,0.0f,0.0f,1.0f);//旋转角度,旋转哪个轴修改哪个轴

正交投影与2DUI元素的绘制

备注:透视投影,进大远小。

1.根据屏幕像素坐标来写绘图数据,而不需要3D坐标,使用前提必须写成以下内容才可以正确使用。

float half_width=float(width)/2.0f; //画布的宽
float half_height=float(height)/2.0f;//画布的高
//左边界,有边界,下边界,上边界,最近点,最远点
projectionMatrix=glm::ortho(-half_width,half_width,-half_height,half_height,0.1f,100.0f);

控制UI前后关系的方法之一

1.通过修改模型矩阵来修改UI前后关系。

2.可以通过修改Z的坐标来确定谁覆盖谁,前提是需要开启深度缓冲区才能管理物体远近关系。

glEnable(GL_DEPTH_TEST)

使用索引数据绘制UI

1.定义一个 GLuint ibo;//index buffer object ,element array buffer object

    unsigned short indexes[]={ 0,1,2,1,3,2};
    glGenBuffers(1,&ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(unsigned short)*6, nullptr,GL_STATIC_DRAW);//alloc gpu
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,sizeof(unsigned short)*6,indexes);//cpu -> gpu
    //glBufferData(GL_ARRAY_BUFFER,sizeof(Vertice)*3,vertices,GL_STATIC_DRAW);//cpu -> gpu
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

2.绘制修改,改变的是绘制三角形的方式

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);

    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_SHORT,0);
    //glDrawArrays(GL_TRIANGLE_STRIP,0,4);

    glUniformMatrix4fv(modelMatrixLocation,1,GL_FALSE,glm::value_ptr(modelMatrix2));
    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_SHORT,0);
    //glDrawArrays(GL_TRIANGLE_STRIP,0,4);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

封装VBO和IBO相关API

GLuint CreateBufferObject(GLenum type,void * data,int size,GLenum usage){
    GLuint object_to_ret;
    glGenBuffers(1,&object_to_ret);
    glBindBuffer(type,object_to_ret);
    glBufferData(type,size,data,usage);//cpu -> gpu
    glBindBuffer(type,0);
    return object_to_ret;
}
void UpdateBufferObject(GLuint object,GLenum type,void * data,int size,int offset){
    glBindBuffer(type,object);
    glBufferSubData(type,offset,size,data);//cpu -> gpu
    glBindBuffer(type,0);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

༄yi笑奈何

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值