OpenGL ES2学习笔记4-- 画点

代码效果

打开OpenGL Console,把下面的代码复制到编辑器里:

import java.nio.ByteBuffer
import java.nio.ByteOrder
import javax.media.opengl.GL

def vertexshadercode = """
  attribute vec4 a_Position;

  void main() {                              
    gl_Position = a_Position;
    gl_PointSize = 10.0;
  }
"""

def fragmentshadercode = """
  precision mediump float; 

  void main() {
    gl_FragColor = vec4(0.7,0.0,0.3,1.0);
  }
"""

def shaderProgram = glob.compileAndLink(vertexshadercode,fragmentshadercode)
def aPositionLocation = shaderProgram.getAttribLocation("a_Position")
shaderProgram.use();


def BYTES_PER_FLOAT = 4
def POSITION_ELEMENT_COUNT = 2
def POINT_COUNT = 3

def vertices = [
  0.0f,0.0f,0.5f,-0.2f,-0.2f
] as float[];

def vertexData = ByteBuffer
        .allocateDirect(vertices.length * BYTES_PER_FLOAT)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer()
vertexData.put(vertices)
vertexData.position(0)
gl.glVertexAttribPointer(aPositionLocation,        POSITION_ELEMENT_COUNT,gl.GL_FLOAT,false,vertexData)
gl.glEnabLevertexAttribArray(aPositionLocation)


gl.glClear(gl.GL_COLOR_BUFFER_BIT)
gl.glDrawArrays(gl.GL_POINTS,POINT_COUNT)
点击Run Script按钮,应该会看到三个点出现在画布上:

Vertex Shader代码

attribute vec4 a_Position;

  void main() {                              
    gl_Position = a_Position;
    gl_PointSize = 10.0;
  }
Vertex Shader的工作是对顶点进行各种变换,所以必须通过某种方式把顶点属性(比如位置)传递给Vertex Shader。 attribute关键字告诉OpenGL,通过a_Position把顶点属性传递给Vertex Shader。vec4是GLSL语言内置的 数据类型,是包含四个float的 向量,可以代表顶点的 xyz坐标和w

像C语言一样,Shader程序的入口也是main()方法gl_Position是GLSL语言的一个特殊变量,表示处理后的顶点位置。这里我们只是简单的把a_Position赋值给gl_Position,不做任何变换。

gl_PointSize也是一个GLSL特殊变量,通过它我们告诉OpenGL把点画成10x10个像素大。

Fragment Shader代码

#ifdef GL_ES
  precision mediump float; 
  #endif 

  void main() {
    gl_FragColor = vec4(0.7,1.0);
  }
第一行定义认的浮点数精度,可选精度包括 lowp、mediump和highp。gl_FragColor是个特殊变量,表示 光栅化Fragment的颜色。

编译和链接Shader

def shaderProgram = glob.compileAndLink(vertexshadercode,fragmentshadercode)
def aPositionLocation = shaderProgram.getAttribLocation("a_Position")
shaderProgram.use();
第一行代码编译和链接Shader代码

第二行代码获取Vertex Shader代码里的a_Position位置,后面会用到:

public class ShaderProgram extends GLObject {
    
    public int getAttribLocation(String aName) {
        return getGL().glGetAttribLocation(objectId,aName);
    }
    
    ...
}
第三行把链接好的Shader Program设置为激活状态:

public class ShaderProgram extends GLObject {
    
    public void use() {
        getGL().gluseProgram(objectId);
    }
    ...
}

顶点数据

def vertices = [
  // x    y 
  0.0f,-0.2f
] as float[];

顶点数据包含三个顶点,每个顶点只定义了x和y坐标,OpenGL会自动把z的值设置成0,把w的值设置成1。

NDC

OpenGL工作在一个叫做NDC(normalized Device Coordinates)的坐标系统下,在这个坐标系统中,x、y和z的值全部都坐落在[-1,+1]范围内,超出这个范围的点会被OpenGL忽略。因为我们直接使用OpenGL的NDC坐标系统,所以顶点坐标的值在-1到+1之间。

把顶点数据和Shader关联

def vertexData = ByteBuffer
        .allocateDirect(vertices.length * BYTES_PER_FLOAT)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer()
vertexData.put(vertices)
vertexData.position(0)
gl.glVertexAttribPointer(aPositionLocation,POSITION_ELEMENT_COUNT,vertexData)
gl.glEnabLevertexAttribArray(aPositionLocation)
通过调用 glVertexAttribPointer()方法,我们把顶点数据和Vertex Shader里的a_Position联系起来,这样OpenGL就会把vertexData里的顶点依次取出交给Shader处理。

POSITION_ELEMENT_COUNT参数告诉OpenGL,vertexData里的顶点只包含x和y坐标。GL_FLOAT参数告诉OpenGL,把vertexData当做float数组来看待。

glEnableVertexAttribArray()方法激活顶点数据。

画点

gl.glClear(gl.GL_COLOR_BUFFER_BIT)
gl.glDrawArrays(gl.GL_POINTS,POINT_COUNT)
glClear()清除屏幕, glDrawArrays()最终把三个点画在了屏幕上。OpenGL实际上只能绘制 点、线或三角形GL_POINTS参数告诉OpenGL我们想要画的是点。POINT_COUNT参数告诉OpenGL画三个点。

相关文章

背景:    8月29日,凌晨4点左右,某服务告警,其中一个...
https://support.smartbear.comeadyapi/docs/soapui/steps/g...
有几个选项可用于执行自定义JMeter脚本并扩展基线JMeter功能...
Scala和Java为静态语言,Groovy为动态语言Scala:函数式编程,...
出处:https://www.jianshu.com/p/ce6f8a1f66f4一、一些内部...
在运行groovy的junit方法时,报了这个错误:java.lang.Excep...