天空 Blond - 着色器
type: channel
link: https://skyblond.info/tag/%E7%9D%80%E8%89%B2%E5%99%A8/
items: 【代码札记】使用 LWJGL 和 OpenGL 最优雅的画圆

【代码札记】使用 LWJGL 和 OpenGL 最优雅的画圆
type: item
date: 2021-04-13T21:04:52+08:00
description: 上一篇文章通过使用VBO来改善程序的运行效率，但程序的计算还是在CPU侧执行。本文将使用着色器，将运算放在GPU上，并获得一定的性能提升。前言着色器是运行在GPU上的一段程序。按照OpenGL对渲染流水线的定义，本文我们将自定义两个着色器：顶点着色器用于计算圆上的每一个点的坐标，片段着色器用于计算所有待呈现片段的颜色。通过操作这两个着色器，我们能够实现利用显卡计算每一个点的坐标，并给最终画出来的圆上色。在这个过程中CPU不再进行一大堆三角函数的运算，而更注重程序运行流程的控制。预备着色器在使用着色器之前，先创建一个工具类：package info.skyblond.antSimu.opengl import org.lwjgl.opengl.GL20.* import org.lwjgl.system.MemoryUtil import java.nio.FloatBuffer import java.nio.charset.StandardCharsets class Shader( private val filename: String ) { private val program: Int private val vertexesShader: Int private val fragmentShader: Int init { program = glCreateProgram() vertexesShader = glCreateShader(GL_VERTEX_SHADER) glShaderSource(vertexesShader, readShaderFileContent("/shaders/$filename.vert")) glCompileShader(vertexesShader) require(glGetShaderi(vertexesShader, GL_COMPILE_STATUS) == 1) { "Unable to compile vertex shader: '/shaders/$filename.vert':" + "\n${glGetShaderInfoLog(vertexesShader)}" } fragmentShader = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(fragmentShader, readShaderFileContent("/shaders/$filename.frag")) glCompileShader(fragmentShader) require(glGetShaderi(fragmentShader, GL_COMPILE_STATUS) == 1) { "Unable to compile fragment shader: '/shaders/$filename.frag'" + "\n${glGetShaderInfoLog(fragmentShader)}" } glAttachShader(program, vertexesShader) glAttachShader(program, fragmentShader) glBindAttribLocation(program, 0, "index") glLinkProgram(program) require(glGetProgrami(program, GL_LINK_STATUS) == 1) { "Failed to link program:" + "\n${glGetProgramInfoLog(program)}" } glValidateProgram(program) require(glGetProgrami(program, GL_VALIDATE_STATUS) == 1) { "Failed to validate program:" + "\n${glGetProgramInfoLog(program)}" } } fun setUniform(name: String, value: Int) { val location = glGetUniformLocation(program, name) require(location != -1) {"Invalidate location returned"} glUniform1i(location, value) } fun setUniform(name: String, value: Double) { val location = glGetUniformLocation(program, name) require(location …