Tutorial 12 - Perspective Projection

来源:互联网 发布:java实现迭代器 编辑:程序博客网 时间:2024/05/18 01:23

pipeline.h:

#ifndef PIPELINE_H#definePIPELINE_H#include "math_3d.h"class Pipeline{public:    Pipeline()    {        m_scale      = Vector3f(1.0f, 1.0f, 1.0f);        m_worldPos   = Vector3f(0.0f, 0.0f, 0.0f);        m_rotateInfo = Vector3f(0.0f, 0.0f, 0.0f);    }    void Scale(float ScaleX, float ScaleY, float ScaleZ)    {        m_scale.x = ScaleX;        m_scale.y = ScaleY;        m_scale.z = ScaleZ;    }    void WorldPos(float x, float y, float z)    {        m_worldPos.x = x;        m_worldPos.y = y;        m_worldPos.z = z;    }    void Rotate(float RotateX, float RotateY, float RotateZ)    {        m_rotateInfo.x = RotateX;        m_rotateInfo.y = RotateY;        m_rotateInfo.z = RotateZ;    }    void SetPerspectiveProj(float FOV, float Width, float Height, float zNear, float zFar)    {        m_persProj.FOV    = FOV;        m_persProj.Width  = Width;        m_persProj.Height = Height;        m_persProj.zNear  = zNear;        m_persProj.zFar   = zFar;    }    const Matrix4f *GetTrans();private:    void InitScaleTransform(Matrix4f &m) const;    void InitRotateTransform(Matrix4f &m) const;    void InitTranslationTransform(Matrix4f &m) const;    //==================================================================    //函数名:  InitPerspectiveProj    //功能:    初始化透视矩阵。根据传入的参数宽高比、垂直视角、近z平面和远z平面值计算出透视矩阵。    //输入参数:Matrix4f& m    //返回值:  void    //==================================================================    void InitPerspectiveProj(Matrix4f &m) const;    Vector3f m_scale;    Vector3f m_worldPos;    Vector3f m_rotateInfo;    //透视投影参数    struct    {        float FOV;//摄像机观察垂直视角的大小。        float Width;//投影区域(四边形)的宽        float Height;//投影区域(四边形)的高        float zNear;//近z平面到视点的距离。        float zFar;//远z平面到视点距离。    } m_persProj;    Matrix4f m_transformation;};#endif/* PIPELINE_H */

pipeline.cpp:

#include "pipeline.h"void Pipeline::InitScaleTransform(Matrix4f &m) const{    m.m[0][0] = m_scale.x;    m.m[0][1] = 0.0f;    m.m[0][2] = 0.0f;    m.m[0][3] = 0.0f;        m.m[1][0] = 0.0f;    m.m[1][1] = m_scale.y;    m.m[1][2] = 0.0f;    m.m[1][3] = 0.0f;        m.m[2][0] = 0.0f;    m.m[2][1] = 0.0f;    m.m[2][2] = m_scale.z;    m.m[2][3] = 0.0f;    m.m[3][0] = 0.0f;        m.m[3][1] = 0.0f;    m.m[3][2] = 0.0f;    m.m[3][3] = 1.0f;}void Pipeline::InitRotateTransform(Matrix4f &m) const{    Matrix4f rx, ry, rz;    const float x = ToRadian(m_rotateInfo.x);    const float y = ToRadian(m_rotateInfo.y);    const float z = ToRadian(m_rotateInfo.z);    rx.m[0][0] = 1.0f;    rx.m[0][1] = 0.0f;    rx.m[0][2] = 0.0f;    rx.m[0][3] = 0.0f;        rx.m[1][0] = 0.0f;    rx.m[1][1] = cosf(x);    rx.m[1][2] = -sinf(x);    rx.m[1][3] = 0.0f;        rx.m[2][0] = 0.0f;    rx.m[2][1] = sinf(x);    rx.m[2][2] = cosf(x);    rx.m[2][3] = 0.0f;        rx.m[3][0] = 0.0f;    rx.m[3][1] = 0.0f;    rx.m[3][2] = 0.0f;    rx.m[3][3] = 1.0f;    ry.m[0][0] = cosf(y);    ry.m[0][1] = 0.0f;    ry.m[0][2] = -sinf(y);    ry.m[0][3] = 0.0f;        ry.m[1][0] = 0.0f;    ry.m[1][1] = 1.0f;    ry.m[1][2] = 0.0f;    ry.m[1][3] = 0.0f;        ry.m[2][0] = sinf(y);    ry.m[2][1] = 0.0f;    ry.m[2][2] = cosf(y);    ry.m[2][3] = 0.0f;        ry.m[3][0] = 0.0f;    ry.m[3][1] = 0.0f;    ry.m[3][2] = 0.0f;    ry.m[3][3] = 1.0f;    rz.m[0][0] = cosf(z);    rz.m[0][1] = -sinf(z);    rz.m[0][2] = 0.0f;    rz.m[0][3] = 0.0f;        rz.m[1][0] = sinf(z);    rz.m[1][1] = cosf(z);    rz.m[1][2] = 0.0f;    rz.m[1][3] = 0.0f;        rz.m[2][0] = 0.0f;    rz.m[2][1] = 0.0f;    rz.m[2][2] = 1.0f;    rz.m[2][3] = 0.0f;        rz.m[3][0] = 0.0f;    rz.m[3][1] = 0.0f;    rz.m[3][2] = 0.0f;    rz.m[3][3] = 1.0f;    m = rz * ry * rx;}void Pipeline::InitTranslationTransform(Matrix4f &m) const{    m.m[0][0] = 1.0f;    m.m[0][1] = 0.0f;    m.m[0][2] = 0.0f;    m.m[0][3] = m_worldPos.x;        m.m[1][0] = 0.0f;    m.m[1][1] = 1.0f;    m.m[1][2] = 0.0f;    m.m[1][3] = m_worldPos.y;        m.m[2][0] = 0.0f;    m.m[2][1] = 0.0f;    m.m[2][2] = 1.0f;    m.m[2][3] = m_worldPos.z;        m.m[3][0] = 0.0f;    m.m[3][1] = 0.0f;    m.m[3][2] = 0.0f;    m.m[3][3] = 1.0f;}void Pipeline::InitPerspectiveProj(Matrix4f &m) const{    const float ar         = m_persProj.Width / m_persProj.Height;    const float zNear      = m_persProj.zNear;    const float zFar       = m_persProj.zFar;    const float zRange     = zNear - zFar;    const float tanHalfFOV = tanf(ToRadian(m_persProj.FOV / 2.0f));    m.m[0][0] = 1.0f / (tanHalfFOV * ar);    m.m[0][1] = 0.0f;    m.m[0][2] = 0.0f;    m.m[0][3] = 0.0;        m.m[1][0] = 0.0f;    m.m[1][1] = 1.0f / tanHalfFOV;    m.m[1][2] = 0.0f;    m.m[1][3] = 0.0;        m.m[2][0] = 0.0f;    m.m[2][1] = 0.0f;    m.m[2][2] = (-zNear - zFar) / zRange ;    m.m[2][3] = 2.0f * zFar * zNear / zRange;        m.m[3][0] = 0.0f;    m.m[3][1] = 0.0f;    m.m[3][2] = 1.0f;    m.m[3][3] = 0.0;}const Matrix4f *Pipeline::GetTrans(){    Matrix4f ScaleTrans, RotateTrans, TranslationTrans, PersProjTrans;    InitScaleTransform(ScaleTrans);    InitRotateTransform(RotateTrans);    InitTranslationTransform(TranslationTrans);    InitPerspectiveProj(PersProjTrans);    m_transformation = PersProjTrans * TranslationTrans * RotateTrans * ScaleTrans;    return &m_transformation;}

perspectiveProjection.cpp:

/*平行投影,就是把顶点垂直的投向投影平面,常用在cad或者机械制图中。另外一种投影是透视投影,这种投影能较好的使二维投影显示立体感,因为符合人眼观看物体透视原理*///////////////////////////////////////////////////////////////////////*程序内容:学习透视投影  程序分析:1)初始化glut2)设置回调函数3) 初始化glew4)设置清除背景颜色5)创建顶点缓存对象6)创建索引缓冲对象7)编译shader对象8)开始内部循环  程序结果:利用透视投影绘制旋转的四面体*/////////////////////////////////////////////////////////////////////#include <stdio.h>#include <string.h>#include <assert.h>#include <math.h>#include <GL/glew.h>#include <GL/freeglut.h>#include "pipeline.h"#pragma comment(lib, "glew32.lib")#pragma comment(lib, "glew32mx.lib")#pragma comment(lib, "freeglut.lib")#define WINDOW_WIDTH 1024#define WINDOW_HEIGHT 768GLuint VBO;GLuint IBO;GLuint gWorldLocation;/* 投影矩阵乘以顶点位置,这时得到的顶点坐标就为裁剪空间, 再经过透视除法后,就是所谓的归一化裁剪空间。*/static const char *pVS = "                                                          \n\#version 330                                                                        \n\                                                                                    \n\layout (location = 0) in vec3 Position;                                             \n\                                                                                    \n\uniform mat4 gWorld;                                                                \n\                                                                                    \n\out vec4 Color;                                                                     \n\                                                                                    \n\void main()                                                                         \n\{                                                                                   \n\    gl_Position = gWorld * vec4(Position, 1.0);                                     \n\    Color = vec4(clamp(Position, 0.0, 1.0), 1.0);                                   \n\}";static const char *pFS = "                                                          \n\#version 330                                                                        \n\                                                                                    \n\in vec4 Color;                                                                      \n\                                                                                    \n\out vec4 FragColor;                                                                 \n\                                                                                    \n\void main()                                                                         \n\{                                                                                   \n\    FragColor = Color;                                                              \n\}";static void RenderSceneCB(){    glClear(GL_COLOR_BUFFER_BIT);    static float Scale = 0.0f;    Scale += 0.1f;    Pipeline p;    //设置各个变换矩阵参数    p.Rotate(0.0f, Scale, 0.0f);    p.WorldPos(0.0f, 0.0f, 5.0f);    //调用设置透视矩阵参数函数    p.SetPerspectiveProj(30.0f, WINDOW_WIDTH, WINDOW_HEIGHT, 1.0f, 100.0f);    //传递给Uniform变量    glUniformMatrix4fv(gWorldLocation, 1, GL_TRUE, (const GLfloat *)p.GetTrans());    glEnableVertexAttribArray(0);    glBindBuffer(GL_ARRAY_BUFFER, VBO);    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);    glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);    glDisableVertexAttribArray(0);    glutSwapBuffers();}static void InitializeGlutCallbacks(){    glutDisplayFunc(RenderSceneCB);    glutIdleFunc(RenderSceneCB);}static void CreateVertexBuffer(){    Vector3f Vertices[4];    Vertices[0] = Vector3f(-1.0f, -1.0f, 0.5773f);    Vertices[1] = Vector3f(0.0f, -1.0f, -1.15475f);    Vertices[2] = Vector3f(1.0f, -1.0f, 0.5773f);    Vertices[3] = Vector3f(0.0f, 1.0f, 0.0f);    glGenBuffers(1, &VBO);    glBindBuffer(GL_ARRAY_BUFFER, VBO);    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);}static void CreateIndexBuffer(){    unsigned int Indices[] = { 0, 3, 1,                               1, 3, 2,                               2, 3, 0,                               0, 2, 1                             };    glGenBuffers(1, &IBO);    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);}static void AddShader(GLuint ShaderProgram, const char *pShaderText, GLenum ShaderType){    GLuint ShaderObj = glCreateShader(ShaderType);    if (ShaderObj == 0)    {        fprintf(stderr, "Error creating shader type %d\n", ShaderType);        exit(0);    }    const GLchar *p[1];    p[0] = pShaderText;    GLint Lengths[1];    Lengths[0] = strlen(pShaderText);    glShaderSource(ShaderObj, 1, p, Lengths);    glCompileShader(ShaderObj);    GLint success;    glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);    if (!success)    {        GLchar InfoLog[1024];        glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);        fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);        exit(1);    }    glAttachShader(ShaderProgram, ShaderObj);}static void CompileShaders(){    GLuint ShaderProgram = glCreateProgram();    if (ShaderProgram == 0)    {        fprintf(stderr, "Error creating shader program\n");        exit(1);    }    AddShader(ShaderProgram, pVS, GL_VERTEX_SHADER);    AddShader(ShaderProgram, pFS, GL_FRAGMENT_SHADER);    GLint Success = 0;    GLchar ErrorLog[1024] = { 0 };    glLinkProgram(ShaderProgram);    glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);    if (Success == 0)    {        glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);        fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);        exit(1);    }    glValidateProgram(ShaderProgram);    glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);    if (!Success)    {        glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);        fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);        exit(1);    }    glUseProgram(ShaderProgram);    gWorldLocation = glGetUniformLocation(ShaderProgram, "gWorld");    assert(gWorldLocation != 0xFFFFFFFF);}int main(int argc, char **argv){    glutInit(&argc, argv);    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);    glutInitWindowPosition(100, 100);    glutCreateWindow("Tutorial 12");    InitializeGlutCallbacks();    // Must be done after glut is initialized!    GLenum res = glewInit();    if (res != GLEW_OK)    {        fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));        return 1;    }    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);    CreateVertexBuffer();    CreateIndexBuffer();    CompileShaders();    glutMainLoop();    return 0;}


原创粉丝点击