前面的文章里,基本上都忽略了顶点的z坐标和w坐标,直接把OpenGL当做2D API来使用,本篇文章介绍一下w坐标的用处。
为了在2D的屏幕上表现出3D效果,OpenGL使用的是一种叫做透视的古老技术。说的更具体一点,Vertex Shader处理后的顶点坐标,并不是直接被OpenGL使用,而是还要经过Perspective Division处理。也就是说x、y和z坐标会被w除,w越大,得到的结果就越小,也就越接近0,看上去就越远。
在OpenGL Console里执行下面的脚本:
import java.nio.ByteBuffer import java.nio.ByteOrder import javax.media.opengl.GL import org.glob.math.Matrix4f // projection matrix float aspectRatio = (width>height ? width/height : height/width) def projectionMatrix = (width > height) ? Matrix4f.orthoM(-aspectRatio, aspectRatio, -1f, 1f, -1f, 1f) : Matrix4f.orthoM(-1f, 1f, -aspectRatio, aspectRatio, -1f, 1f) // shaders def vertexShaderCode = """ uniform mat4 u_Matrix; attribute vec4 a_Position; void main() { gl_Position = u_Matrix * a_Position; } """ def fragmentShaderCode = """ #ifdef GL_ES precision mediump float; #endif void main() { gl_FragColor = vec4(0.5, 0.8, 0.3, 1.0); } """ def shaderProgram = glob.compileAndLink(vertexShaderCode, fragmentShaderCode) def aPositionLocation = shaderProgram.getAttribLocation("a_Position") shaderProgram.use() shaderProgram.getUniform("u_Matrix").setMatrix4fv(projectionMatrix.floats) // vertex data def BYTES_PER_FLOAT = 4 def POSITION_ELEMENT_COUNT = 4 def POINT_COUNT = 4 def vertices = [ // triangle fan // x y z w -0.5f, -0.5f, 0, 1, -0.5f, 0.5f, 0, 2, 0.5f, 0.5f, 0, 2, 0.5f, -0.5f, 0, 1, ] 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, 0, vertexData) gl.glEnableVertexAttribArray(aPositionLocation) // draw triangle gl.glClear(gl.GL_COLOR_BUFFER_BIT) gl.glDrawArrays(gl.GL_TRIANGLE_FAN, 0, POINT_COUNT)效果:
代码和前一篇文章基本上类似,唯一的区别是顶点数据的定义:
def POSITION_ELEMENT_COUNT = 4 def vertices = [ // triangle fan // x y z w -0.5f, -0.5f, 0, 1, -0.5f, 0.5f, 0, 2, 0.5f, 0.5f, 0, 2, 0.5f, -0.5f, 0, 1, ] as float[]顶点坐标有原来的x和y扩充为xyzw,z坐标为0。靠上的两个顶点的w值为2,因此看起来更远一些。靠下的两个顶点的w值为1,所以看起来更近一些。