首页 > 其他分享 >编译着色器并在屏幕上绘图

编译着色器并在屏幕上绘图

时间:2024-01-31 17:36:00浏览次数:30  
标签:val 0.5 编译 0f 1f 绘图 着色器

一.前言

  本篇文章会继续上一篇文章开始的工作,在这篇文章中,我们首先会加载并编译前面定义的着色器,然后把他们链接在一起放在OpenGL的一个程序里,接下来就可以使用这个着色器程序在屏幕上绘制空气曲棍球桌子结构了。

 二.加载着色器

  1.我们已经为着色器写了代码,下一步则要把他们加载进内存中。为此,我们首先需要定义一个可以从资源文件夹中读取那些代码的方法。我们可以写一个工具类TextResourceReader,用于读取着色器代码,代码如下:

class TextResourceReader {
    companion object{
        fun readTextFileFromResource(context: Context, id:Int):String{
            val stringBuilder=StringBuilder()
            val inputStream=context.resources.openRawResource(id)
            val inputStreamReader= InputStreamReader(inputStream)
            val bufferedReader= BufferedReader(inputStreamReader)
            var nextLine:String?=bufferedReader.readLine()
            while(nextLine!=null){
                stringBuilder.append(nextLine)
                stringBuilder.append("\n")
                nextLine=bufferedReader.readLine()
            }
            return stringBuilder.toString()
        }
    }
}

  2.下面,我们使用这个工具类去读取着色器代码,我们需要修改MyRenderer.kt文件,在onSurfaceCreated方法的末尾加入如下代码:

//读取着色器代码
val vertexShaderCode=TextResourceReader.readTextFileFromResource(context,R.raw.simple_vertex_shader)
val fragmentShaderCode=TextResourceReader.readTextFileFromResource(context,R.raw.simple_fragment_shader)

  3.由于这个工具类中的方法需要传入Context对象,所以我们需要给MyRenderer类新增一个成员变量context,并在MainActivity类中传入this引用。

三.编译着色器,链接程序,绘制图形

  1.现在,我们已经把每个着色器的源代码读取出来了,下一步就是编译每个着色器了。我们可以新建一个辅助类ShaderHelper,它可以创建新的着色器对象,编译着色器代码并返回代表那段着色器代码的着色器对象。代码入下:

class ShaderHelper {
    companion object{
        //编译顶点着色器
        fun compileVertexShader(shaderCode:String):Int{
            return compileShader(GL_VERTEX_SHADER,shaderCode)
        }
        //编译片段着色器
        fun compileFragmentShader(shaderCode:String):Int{
            return compileShader(GL_FRAGMENT_SHADER,shaderCode)
        }
        //根据不同类型编译不同的着色器
        fun compileShader(type:Int,shaderCode:String):Int{
            //创建着色器对象
            val shaderObjectId=glCreateShader(type)
            //返回0表示创建失败
            if(shaderObjectId==0){
                Log.i("ShaderHelper","Could not create new shader")
                return 0
            }
            //上传着色器源代码
            glShaderSource(shaderObjectId,shaderCode)
            //编译着色器对象
            glCompileShader(shaderObjectId)
            //检查着色器是否编译成功,并把结果存入数组的首地址
            val status= IntArray(1)
            glGetShaderiv(shaderObjectId,GL_COMPILE_STATUS,status,0)
            //结果为0表示编译着色器失败
            if(status[0]==0){
                glDeleteShader(shaderObjectId)//删除着色器对象
                return 0
            }
            return shaderObjectId
        }
    }
}

  2.接下来,我们在MyRenderer这个类中使用以上定义的辅助类编译顶点着色器和片段着色器,在onSurfaceCreated方法末尾加入如下代码:

//编译顶点着色器和片段着色器
val vertexShader=ShaderHelper.compileVertexShader(vertexShaderCode)
val fragmentShader=ShaderHelper.compileFragmentShader(fragmentShaderCode)

  3.把着色器一起链接进OpenGL程序,编译完顶点着色器和片段着色器后,我们需要把他们绑定到一起,然后放入单个的OpenGL程序中。我们在ShaderHelper类中新增一个方法linkProgram()用于实现这个链接功能,代码如下:

        fun linkProgram(vertexShaderId:Int,fragmentShaderId:Int):Int{
            //新建程序对象
            val programObjectId=glCreateProgram()
            if(programObjectId==0){//新建程序对象失败
                Log.i("ShaderHelper","Could not create programObject")
                return 0
            }
            //附上顶点着色器对象和片段着色器对象
            glAttachShader(programObjectId,vertexShaderId)
            glAttachShader(programObjectId,fragmentShaderId)
            //链接程序
            glLinkProgram(programObjectId)
            //检查程序是否链接成功
            val status=IntArray(1)
            glGetProgramiv(programObjectId,GL_LINK_STATUS,status,0)
            if(status[0]==0){//程序链接失败
                glDeleteProgram(programObjectId)//删除程序对象
                Log.i("ShaderHelper","Could not link program")
                return 0
            }
            return programObjectId
        }

  4.修改MyRenderer类,新增一个成员变量program,用于存储程序对象id,并在onSurfaceCreated方法末尾加入如下代码:

//链接并使用这个OpenGL程序
program=ShaderHelper.linkProgram(vertexShader,fragmentShader)
glUseProgram(program)

  5.关联属性和顶点数据的数组,也就是告诉OpenGL到哪里去找属性a_Position所对应的数据,代码如下:

//从开头处开始读取数据
vertexData.position(0)
//关联属性和顶点数据的数组
glVertexAttribPointer(0, POSITION_COMPONENT_COUNT, GL_FLOAT,false,0,vertexData)
//使能顶点数组
glEnableVertexAttribArray(0)

  6.glVertexAttribPointer()函数就是用来绑定属性和顶点数组的,它的定义如下:

public static void glVertexAttribPointer(
        int indx,//属性的位置,这里指a_Position的位置
        int size,//每个属性的数据计数,这里我们只用了两个,x和y
        int type,//数据的类型
        boolean normalized,//只有使用整型数据时才有意义
        int stride,//步长,只有当数组中存储的属性多于一个才有意义,比如同时存储顶点位置和颜色。这里只存储了位置,设为0即可
        java.nio.Buffer ptr//缓冲区指针
)

  7.开始绘制,在onDrawFrame函数的末尾加入如下代码:

//绘制矩形
glUniform4f(0,1f,1f,1f,1f)
glDrawArrays(GL_TRIANGLES,0,6)
//绘制分割线
glUniform4f(0,1f,0f,0f,1f)
glDrawArrays(GL_LINES,6,2)
//绘制木槌,用点表示
glUniform4f(0,0f,1f,0f,1f)
glDrawArrays(GL_POINTS,8,1)
glUniform4f(0,0f,1f,0f,1f)
glDrawArrays(GL_POINTS,9,1)

  现在可以运行程序,但是此时我们只能看到桌子的一个角,看不到完整的桌子。想要解决这个问题,我们需要知道OpenGL怎么将我们定义的坐标映射到屏幕上实际的物理坐标的。OpenGL希望在所有的顶点着色器运行后,所有可见的点都变为标准化设备坐标,也就是说x,y,z的范围都在-1到1之间,超出这个范围的点都是不可见的。所以我们需要重新修改下顶点坐标,让其在-1到1之间,修改后的坐标如下:

val tableVertices=floatArrayOf(
            //Triangle one
            -0.5f,-0.5f,
            0.5f,0.5f,
            -0.5f,0.5f,
            //Triangle two
            -0.5f,-0.5f,
            0.5f,-0.5f,
            0.5f,0.5f,
            //Mid Line
            -0.5f,0f,
            0.5f,0f,
            //Mallets
            0f,-0.25f,
            0f,0.25f,
        )

  修改完顶点坐标后,我们再把清除屏幕的颜色设置为黑色,就可以看到下面的效果了:

       

 

标签:val,0.5,编译,0f,1f,绘图,着色器
From: https://www.cnblogs.com/luqman/p/17999006

相关文章

  • MySQL Shell 8.0.32 for GreatSQL编译二进制包
    MySQLShell8.0.32forGreatSQL编译二进制包构建MySQLShell8.0.32forGreatSQL0.写在前面之前已经写过一篇前传MySQLShell8.0.32forGreatSQL编译安装,最近再次编译MySQLShell二进制包时,发现了一些新问题,因此重新整理更新本文档。1.几处新问题这次编译MySQLShe......
  • npm编译vue出错:Error code CERT_HAS_EXPIRED
    [Error]Theerrormessageisabouttheregistryhttps://npm.sap.com/youused.npmERR!codeCERT_HAS_EXPIREDnpmERR!errnoCERT_HAS_EXPIREDnpmERR!requesttohttps://npm.sap.com/@sap%2fcdsfailed,reason:certificatehasexpired[Solution]runcommand......
  • Qt 使用MSVC2017编译报错: C1083:无法打开包括文件: “stddef.h“的解决方案
    之前安装过QT的好几个版本:5.9,5.12,5.15,编译过项目。现在使用QT5.12.6+MSVC2017编译项目出现如下图所示报错,困扰了我2天。一开始,我通过卸载重装QT和 VS2017 都没有解决问题。今天晚上找到一个办法,就是在QT“项目”设置里面将头文件目录配置进去,终于将问题解决......
  • openssh 9.6交叉编译ls1043
    准备工作zlib:官网下载:https://www.zlib.net版本:zlib-1.2.2.tar.gzopenssl:官网下载:https://www.openssl.org/source版本:openssl-1.1.1k.tar.gzopenssh:官网下载:http://www.openssh.com/portable.html阿里云镜像:https://mirrors.aliyun.com/pub/OpenBSD/OpenSSH/portable......
  • IDEA编译生成可运行jar包 和 运行jar包报java.lang.NoClassDefFoundError错误,注意 MF
    IDEA编译生成可运行jar包和运行jar包报java.lang.NoClassDefFoundError错误,注意MF文件目录不要用默认目录,改成项目根目录运行环境:操作系统:ubuntu20.04javaversion:openjdkversion"11"2018-09-25OpenJDKRuntimeEnvironment18.9(build11+28)OpenJDK64-BitServer......
  • mips交叉编译相关库文件,主要做以后参考
    1.mips交叉编译paho-mqtt3ascmake-DCMAKE_INSTALL_PREFIX=${pwd}/install-DPAHO_WITH_SSL=TRUE-DPAHO_BUILD_SAMPLES=TRUE-DCMAKE_C_COMPILER=/opt/mips-linux-gnueabihf/bin/mips-linux-gnu-gcc-DPAHO_BUILD_DOCUMENTATION=TRUE-DOPENSSL_LIB_SEARCH_PATH=/usr/mips/lib......
  • IDEA编译报错:Error:Kotlin: Module was compiled with an incompatible version of Ko
    问题Error:Kotlin:ModulewascompiledwithanincompatibleversionofKotlin.Thebinaryversionofitsmetadatais1.6.0,expectedversionis1.1.13.Warning:Kotlin:RuntimeJARfilesintheclasspathshouldhavethesameversion.Thesefileswerefoundi......
  • 有关UE5在VisualStudio升级后产生C++无法编译的问题及处理方案
    哈喽大家好,我是咕噜美乐蒂,很高兴又见面啦!最近,许多使用UE5的游戏开发者遇到了一个问题:在VisualStudio升级后,他们的C++代码无法编译。这个问题可能是由于UE5工程和VS之间的版本不兼容导致的。本文将深入探讨这个问题的原因以及如何解决它。一、问题的产生原因UE5是一款基于C++的游戏......
  • linux内核-2.Linux 内核makefile编译过程
    1zImage编译_all是默认目标,如果使用命令make或者makeall编译Linux的话此目标就会被匹配。KBUILD_EXTMOD为空的,因此194行的代码成立,因此_all依赖all。all又依赖vmlinux,开始编译vmlinux。makeARCH=armCROSS_COMPILE=arm-linux-gnueabihf-distcleanmakeARCH=armCR......
  • OPENSSL1.1交叉编译编译异常处理
    openssl 编译异常报以下错误Operatingsystem:x86_64-whatever-linux2"glob"isnotexportedbytheFile::GlobmoduleCan'tcontinueafterimporterrorsat./Configureline18.BEGINfailed--compilationabortedat./Configureline18."glob"......