OpenGL ES2学习笔记(11)--神秘的w

前面的文章里,基本上都忽略了顶点的z坐标和w坐标,直接把OpenGL当做2D API来使用,本篇文章介绍一下w坐标的用处。

透视

为了在2D的屏幕上表现出3D效果,OpenGL使用的是一种叫做透视的古老技术。说的更具体一点,Vertex Shader处理后的顶点坐标,并不是直接被OpenGL使用,而是还要经过Perspective Division处理。也就是说x、y和z坐标会被w除,w越大,得到的结果就越小,也就越接近0,看上去就越远。

OpenGL ES2学习笔记(11)--神秘的w_第1张图片

代码和效果

在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)
效果:

OpenGL ES2学习笔记(11)--神秘的w_第2张图片

代码解释

代码和前一篇文章基本上类似,唯一的区别是顶点数据的定义:

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,所以看起来更近一些。


你可能感兴趣的:(OpenGL,es)