OpenGL

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

2022-11-29  本文已影响0人  itfitness

目录

相关文章

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

上一篇下一篇

猜你喜欢

热点阅读