代码和效果
打开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画三个点。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。