美文网首页OpenGL
OpenGL系列之九:glsl着色器语言

OpenGL系列之九:glsl着色器语言

作者: itfitness | 来源:发表于2022-11-29 17:18 被阅读0次

    目录

    相关文章

    OpenGL系列之一:OpenGL第一个程序
    OpenGL系列之二:绘制三角形
    OpenGL系列之三:三角形顶点增加颜色
    OpenGL系列之四:绘制四边形
    OpenGL系列之五:绘制点和线
    OpenGL系列之六:绘制立方体
    OpenGL系列之七:纹理贴图
    OpenGL系列之八:立方体纹理贴图

    实现效果

    实现步骤

    1.编写glsl文件

    glsl是着色器语言,分为顶点着色器和片元着色器,具体的话我这也不过多介绍了,因为目前我也初学,可以参考以下连接:
    https://gitcode.net/mirrors/wshxbqq/GLSL-Card?utm_source=csdn_github_accelerator
    https://thebookofshaders.com/?lan=ch
    http://www.tastones.com/stackoverflow/glsl/getting-started-with-glsl/first_ogl_4.0_glsl_shader_program/
    这里我编写的比较简单,如下所示:
    顶点着色器vertex.vert

    #version 300 es //指定OpenglES 版本
    //需要C代码传入的两个变量
    layout(location = 0) in vec4 a_position;
    layout(location = 1) in vec4 a_color;
    //需要C代码传入的矩阵
    uniform mat4   u_mat;
    //输出的变量(给片元着色器使用)
    out vec4   o_color;
    
    void main(void)
    {
        //可以通过这里修改颜色值来改变颜色
        o_color = vec4(a_color.r,a_color.g,a_color.b,a_color.a);
        gl_Position = u_mat * a_position;
    }
    

    片元着色器fragment.frag

    #version 300 es //指定OpenglES 版本
    //指定精度
    precision mediump float;
    //顶点着色器输出的,变量名需要相同
    in vec4   o_color;
    //片元着色器输出的,在本案例里就是渲染的颜色
    out vec4 fragColor;
    
    
    void main(void)
    {
        fragColor = o_color;
    }
    
    2.加载glsl文件

    这里进行了封装,基本都是固定的,基本就是加载、连接、设置变量等等,以后也可以直接使用,所以就不过多解释了。
    CCOpenGLShader.h

    
    #ifndef CCOPENGLES_CCOPENGLSHADER_H
    #define CCOPENGLES_CCOPENGLSHADER_H
    
    #include "CCGLPrimitivesDef.h"
    
    class CCOpenGLShader {
    
    public:
        CCOpenGLShader();
        ~CCOpenGLShader();
    
        void Bind();
        void Release();
    
        void InitShadersFromFile(AAssetManager*  pManager, const char* vShader,const char* fshader);
    
        void DisableAttributeArray(const char *name);
        void EnableAttributeArray(const char *name);
        void SetAttributeBuffer(const char* name,GLenum type, const void *values, int tupleSize, int stride = 0);
    
        void SetUniformValue(const char* name, int iValue);
        void SetUniformValue(const char* name, GLfloat fValue);
        void SetUniformValue(const char* name, glm::vec3 vecValue);
        void SetUniformValue(const char* name, glm::mat4 matValue);
    
    private:
        int compileShader(AAssetManager*  m_pAssetManager,const char* sPath, GLint sType);
    private:
        GLuint m_shaderProgram;
    };
    
    
    #endif //CCOPENGLES_CCOPENGLSHADER_H
    

    CCOpenGLShader.cpp

    #include "CCOpenGLShader.h"
    #include <string>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    
    CCOpenGLShader::CCOpenGLShader()
    {
        m_shaderProgram = 0;
    }
    
    CCOpenGLShader::~CCOpenGLShader()
    {
    }
    
    void CCOpenGLShader::InitShadersFromFile(AAssetManager* pManager,const char* vPath, const char* fPath)
    {
        GLuint  vertexId = 0;
        GLuint  fragId = 0;
        vertexId   = compileShader(pManager,vPath ,GL_VERTEX_SHADER);
        fragId     = compileShader(pManager,fPath ,GL_FRAGMENT_SHADER);
    
        char           message[512];
        int            status = 0;
        m_shaderProgram = glCreateProgram();
        if (vertexId != -1)
        {
            glAttachShader(m_shaderProgram, vertexId);
        }
        if (fragId != -1)
        {
            glAttachShader(m_shaderProgram, fragId);
        }
        glLinkProgram(m_shaderProgram);
    
        glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &status);
        if (!status)
        {
            glGetProgramInfoLog(m_shaderProgram, 512, NULL, message);
            LOGE("Get shaderProgram failed: %s",message);
        }
        glDeleteShader(vertexId);
        glDeleteShader(fragId);
    }
    int CCOpenGLShader::compileShader(AAssetManager*  pManager,const char* fName, GLint sType)
    {
        AAsset* file = AAssetManager_open(pManager,fName, AASSET_MODE_BUFFER);
        size_t shaderSize = AAsset_getLength(file);
        char* sContentBuff = (char*)malloc(shaderSize);
        AAsset_read(file, sContentBuff, shaderSize);
        LOGD("SHADERS: %s",sContentBuff);
        unsigned int   shaderID = 0;
        char           message[512]={0};
        int            status = 0;
    
        shaderID = glCreateShader(sType);
        glShaderSource(shaderID, 1, &sContentBuff, (const GLint *)&shaderSize);
        glCompileShader(shaderID);
    
        glGetShaderiv(shaderID, GL_COMPILE_STATUS, &status);
        if (!status)
        {
            glGetShaderInfoLog(shaderID, 512, NULL, message);
            LOGF("Compile Shader Status failed: %s",message);
        }
    
        if(sContentBuff != NULL){
            free(sContentBuff);
            sContentBuff = NULL;
        }
    
        AAsset_close(file);
    
        return shaderID;
    }
    
    
    void CCOpenGLShader::Bind()
    {
        glUseProgram(m_shaderProgram);
    }
    
    void CCOpenGLShader::Release()
    {
        glUseProgram(0);
    }
    
    void CCOpenGLShader::SetUniformValue(const char* name, int iValue)
    {
        glUniform1i(glGetUniformLocation(m_shaderProgram, name), iValue);
    
    }
    
    void CCOpenGLShader::SetUniformValue(const char* name, GLfloat fValue)
    {
        glUniform1f(glGetUniformLocation(m_shaderProgram, name), fValue);
    }
    
    void CCOpenGLShader::SetUniformValue(const char* name, glm::vec3 vec3Value)
    {
        glUniform3fv(glGetUniformLocation(m_shaderProgram, name), 1, glm::value_ptr(vec3Value));
    }
    
    void CCOpenGLShader::SetUniformValue(const char* name, glm::mat4 matValue)
    {
        glUniformMatrix4fv(glGetUniformLocation(m_shaderProgram, name) , 1 , GL_FALSE , glm::value_ptr(matValue));
    }
    
    void CCOpenGLShader::EnableAttributeArray(const char *name)
    {
        GLuint location = glGetAttribLocation(m_shaderProgram, name);
        glEnableVertexAttribArray(location);
    }
    
    void CCOpenGLShader::DisableAttributeArray(const char *name)
    {
        GLuint location = glGetAttribLocation(m_shaderProgram, name);
        glDisableVertexAttribArray(location);
    }
    
    void CCOpenGLShader::SetAttributeBuffer(const char* name,GLenum type, const void *values, int tupleSize, int stride)
    {
        GLuint location = glGetAttribLocation(m_shaderProgram, name);
        glVertexAttribPointer(location,tupleSize,type,GL_FALSE,stride,values);
    }
    
    

    加载的话是根据文件名,获取到Assets文件夹中的文件


    extern "C"
    JNIEXPORT void JNICALL
    Java_com_itfitness_opengldemo_GLRender_ndkInitGL(JNIEnv *env, jobject thiz, jobject assets) {
        ccRender.initGL();
        AAssetManager *astManager = AAssetManager_fromJava (env, assets);
        ccRender.ccOpenGlShader.InitShadersFromFile(astManager,"vertex.vert","fragment.frag");
    }
    

    使用的话基本都是固定的步骤,这里就不贴全部代码了,如下绘制函数所示:

    /**
     * 画三角
     */
    void CCRender::drawTriangle() {
    
        CCFloat7 triangleVert[] ={
                {0,       0.5,    -3,  1,  0,  0,1.0},
                {-0.5,   -0.5,    -3,  0,  1,  0,1.0},
                {0.5,    -0.5,    -3,  0,  0,  1,1.0},
        };
    
    
        m_angle += 0.03f;
    
        glm::mat4x4  cubeMat;
        glm::mat4x4  cubeTransMat = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -3));
        glm::mat4x4  cubeRotMat = glm::rotate(glm::mat4(1.0f),m_angle,glm::vec3(0.0f, 0.0f, -3.0) );
        glm::mat4x4  cubeScaleMat = glm::scale(glm::mat4(1.0f),glm::vec3(0.3f, 0.2f, 0.3) );
    
        //透视投影矩阵,跟之前的glOrthof(-1,1,-1,1,0.1,1000);差不多意思,3.0glOrthof这个API没有了
        glm::mat4 projMat = glm::perspective(glm::radians(60.0f), (float)9/(float)18, 0.0f, 1000.0f);
        cubeMat = projMat * cubeRotMat;
    
        ccOpenGlShader.Bind();
    
        //这里的变量名与glsl中的一样
        //传递矩阵数据
        ccOpenGlShader.SetUniformValue("u_mat",cubeMat);
        //启动顶点变量
        ccOpenGlShader.EnableAttributeArray("a_position");
        //启动着色变量
        ccOpenGlShader.EnableAttributeArray("a_color");
        
        //为变量设置数据
        ccOpenGlShader.SetAttributeBuffer("a_position",GL_FLOAT,triangleVert,3,sizeof(CCFloat7));
        ccOpenGlShader.SetAttributeBuffer("a_color",GL_FLOAT,&triangleVert[0].r,4,sizeof(CCFloat7));
    
        glDrawArrays(GL_TRIANGLES,0,3);
    
        //关闭顶点变量
        ccOpenGlShader.DisableAttributeArray("a_position");
        //关闭着色变量
        ccOpenGlShader.DisableAttributeArray("a_color");
    
        ccOpenGlShader.Release();
    }
    
    3.注意事项

    这里与之前的程序不同,使用了opengl es 3.0,其中有些API不能用了与之前程序相比删除了一些API的使用,然后在创建GLSurfaceView的时候也需要指定opengl es 的版本号

    val glSurfaceView = GLSurfaceView(this)
    glSurfaceView.setEGLContextClientVersion(3)
    glSurfaceView.setRenderer(GLRender(this))
    

    案例源码

    https://gitee.com/itfitness/opengl-glsl

    相关文章

      网友评论

        本文标题:OpenGL系列之九:glsl着色器语言

        本文链接:https://www.haomeiwen.com/subject/vltrfdtx.html