opengl es 2.0游戏与图形编程——2.设置图形投影

来源:互联网 发布:淘宝里的运费险怎么退 编辑:程序博客网 时间:2024/05/22 18:46

注意:本文是读书笔记,代码是使用书中sdk的,主要掌握重点知识,别在意小细节

1.两种投影:正交投影(2d,但可使用z,只是透视完全基于当前屏幕比),透视投影(3d)


2.初始设置矩阵

  模型视图矩阵:物体空间 -> (模型)世界空间 ->(视图) 摄像机空间

  拓展:

[视图变换]  当摄像机的位置和朝向任意时,投影变换及气体类型的变换变得困难。为了简化运算,我们将摄像机变化到世界坐标系原点,并旋转使摄像机的 光轴和世界坐标系z轴正方向一致。    视图变换是从世界坐标系到摄像机坐标系的变换,计算就是将摄像机弄回原点并对齐z轴的变换(也可以是将摄像机从坐标轴原点移动到摄像机当前位置的 逆变换)。  许多计算都在眼睛坐标系中完成,一个常用的就是光照需要在这个空间中实现,因为眼睛位置决定了光照效果,否则的话,很难实现镜面光。因此我们需要将法线坐标转换到眼睛坐标系中。  标准向量(Normal vectors)——从对象坐标系(Object coordinates)变换到视觉坐标系(eye coordinates),它是用来计算光照(lighting calculation)的.注意标准向量(Normal vectors)的变换和顶点的不同。其中视觉矩阵(view matrix)是GL_MODELVIEW逆矩阵的转置矩阵和标准向量(Normal vector是)相乘所得。
  代码:

GFX_set_matrix_mode( MODELVIEW_MATRIX );GFX_load_identity();    vec3 e = {0.0f, -3.0f, 0.0f},    c = {0.0f, 0.0f, 0.0f},    u = {0.0f, 0.0f, 1.0f};        GFX_look_at(&e, &c, &u);        static float y = 0.0f;    y += 0.1f;    GFX_translate(0.0f, y, 0.0f);    GFX_rotate(y * 50.0f, 1.0f, 1.0f, 1.0f);

  投影矩阵:摄像机空间 -> 裁减空间(视锥空间)

// 2d        GFX_set_orthographic((float)height / (float)width, 5.0f, (float)width / (float)height, 1.0f, 100.0f, 0.0f);                // 3d        GFX_set_perspective(45.0f, (float)width / (float)height, 0.01f, 100.0f, 0.0f);

3.使用着色器

  

program = PROGRAM_init( ( char * )"default" );program->vertex_shader = SHADER_init( VERTEX_SHADER, GL_VERTEX_SHADER );   program->fragment_shader = SHADER_init( FRAGMENT_SHADER, GL_FRAGMENT_SHADER );m = mopen( VERTEX_SHADER, 1 );if( m ) {if( !SHADER_compile( program->vertex_shader,     ( char * )m->buffer, DEBUG_SHADERS ) ) exit( 1 );}m = mclose( m );m = mopen( FRAGMENT_SHADER, 1 );if( m ) {if( !SHADER_compile( program->fragment_shader,     ( char * )m->buffer,     DEBUG_SHADERS ) ) exit( 2 ); }  m = mclose( m );   if( !PROGRAM_link( program, DEBUG_SHADERS ) ) exit( 3 );
  上面创建了一个着色器程序,并读取和编译了顶点着色器和片段着色器,然后链接了这个着色器程序。

  下面是绘制时的代码:

if( program->pid ) {char attribute, uniform;glUseProgram( program->pid );uniform = PROGRAM_get_uniform_location( program, ( char * )"MODELVIEWPROJECTIONMATRIX" );glUniformMatrix4fv( uniform,1 /* How many 4x4 matrix */,GL_FALSE /* Transpose the matrix? */, <span style="white-space:pre"></span>( float * )GFX_get_modelview_projection_matrix() );attribute = PROGRAM_get_vertex_attrib_location( program, ( char * )"POSITION" );glEnableVertexAttribArray( attribute );glVertexAttribPointer( attribute, 3, GL_FLOAT, GL_FALSE, 0, POSITION );attribute = PROGRAM_get_vertex_attrib_location( program, ( char * )"COLOR" );glEnableVertexAttribArray( attribute );glVertexAttribPointer( attribute, 4, GL_FLOAT, GL_FALSE, 0, COLOR );glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );}
  先使用来该着色器程序,获取其中定义的全局uniform变量 MODELVIEWPROJECTION 的地址location,并设置其值。

  同理设置了要绘制的顶点多两个属性的值(数组),属性值如下:

static const float POSITION[ 12 ] = {-0.5f, 0.0f, -0.5f, // Down left (pivot point)0.5f, 0.0f, -0.5f, // Up left-0.5f, 0.0f, 0.5f, // Down right0.5f, 0.0f, 0.5f  // Up right};static const float COLOR[ 16 ] = {1.0f, 0.0f, 0.0f, 1.0f, // Red0.0f, 1.0f, 0.0f, 1.0f, // Green0.0f, 0.0f, 1.0f, 1.0f, // Blue1.0f, 1.0f, 0.0f, 1.0f  // Yellow};
  设置好变量和值后就提交渲染了。


4.着色器代码

  顶点着色器:

uniform mediump mat4 MODELVIEWPROJECTIONMATRIX;attribute mediump vec4 POSITION;attribute lowp vec4 COLOR;varying lowp vec4 color;void main( void ) {gl_Position = MODELVIEWPROJECTIONMATRIX * POSITION;color = COLOR;}
  主要就是把cpp里传来的顶点位置属性 左乘了 模型视图 投影矩阵,即被变换到裁剪空间了,并用gl_Position输出。然后给片段着色器传递了一个color变量(varying标记)。

  片段着色器:

varying lowp vec4 color;void main( void ) {gl_FragColor = color;}
  直接输出顶点着色器传来的颜色值。

  最终效果如下:




5.看下cocos2dx

  设置矩阵:

case Projection::_2D:        {            loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);            Mat4 orthoMatrix;            Mat4::createOrthographicOffCenter(0, size.width, 0, size.height, -1024, 1024, &orthoMatrix);            multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, orthoMatrix);            loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);            break;        }                    case Projection::_3D:        {            float zeye = this->getZEye();            Mat4 matrixPerspective, matrixLookup;            loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION);            // issue #1334            Mat4::createPerspective(60, (GLfloat)size.width/size.height, 10, zeye+size.height/2, &matrixPerspective);            multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, matrixPerspective);            Vec3 eye(size.width/2, size.height/2, zeye), center(size.width/2, size.height/2, 0.0f), up(0.0f, 1.0f, 0.0f);            Mat4::createLookAt(eye, center, up, &matrixLookup);            multiplyMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION, matrixLookup);                        loadIdentityMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);            break;        }
  默认是3d方式,投影矩阵里已经乘了一个往屏幕中心看的摄像机矩阵了。

  节点的模型视图矩阵:

Mat4 Node::transform(const Mat4& parentTransform){    return parentTransform * this->getNodeToParentTransform();}
  这个会传递给渲染命令RenderCommand使用,比如:

void TrianglesCommand::useMaterial() const{    //Set texture    GL::bindTexture2D(_textureID);        //set blend mode    GL::blendFunc(_blendType.src, _blendType.dst);        _glProgramState->apply(_mv);}
  被着色器程序状态ProgramState作为内置的全局变量CC_MVMatrix  (还有类似的CC_MVPMatrix)传递给其着色器代码使用。
  着色器代码:

const char* ccPositionColor_vert = STRINGIFY(attribute vec4 a_position;attribute vec4 a_color;\n#ifdef GL_ES\nvarying lowp vec4 v_fragmentColor;\n#else\nvarying vec4 v_fragmentColor;\n#endif\nvoid main(){    gl_Position = CC_MVPMatrix * a_position;    v_fragmentColor = a_color;});

const char* ccPositionColor_frag = STRINGIFY(\n#ifdef GL_ES\nprecision lowp float;\n#endif\nvarying vec4 v_fragmentColor;void main(){    gl_FragColor = v_fragmentColor;});



  

0 0
原创粉丝点击