• 纹理投影流程


    纹理投影流程

    cg toolkit中关于纹理投影的例子

    一    主程序中执行的空间变换

    二    shader执行的render pipe处理

    1           建立视点矩阵

    eyePosition[3];//观察视点位置

    lightPosition[3];//光源位置,或投影视点位置

    center[3];//投影中心,是地形或模型上的一点

    up[3];上向量方向,一般为Y轴正方向

      buildLookAtMatrix(eyePosition[0], eyePosition[1], eyePosition[2],
    center[0], center[1], center[2],
    up[0], up[1], up[2],
    eyeViewMatrix);

    buildLookAtMatrix(lightPosition[0], lightPosition[1], lightPosition[2],
    center[0], center[1], center[2],
    up[0], -up[1], up[2], /* Flip up for projected texture's view */
    lightViewMatrix);
    //buildLookAtMatrix实现
    View Code
    /* Build a row-major (C-style) 4x4 matrix transform based on the
    parameters for gluLookAt.
    */

    static void buildLookAtMatrix(double eyex, double eyey, double eyez,
    double centerx, double centery, double centerz,
    double upx, double upy, double upz,
    float m[16])
    {
    double x[3], y[3], z[3], mag;
    /* Difference eye and center vectors to make Z vector. */
    z[0] = eyex - centerx;
    z[1] = eyey - centery;
    z[2] = eyez - centerz;

    /* Normalize Z. */
    mag = sqrt(z[0]*z[0] + z[1]*z[1] + z[2]*z[2]);
    if (mag) {
    z[0] /= mag;
    z[1] /= mag;
    z[2] /= mag;
    }

    /* Up vector makes Y vector. */
    y[0] = upx;
    y[1] = upy;
    y[2] = upz;

    /* X vector = Y cross Z. */
    x[0] = y[1]*z[2] - y[2]*z[1];
    x[1] = -y[0]*z[2] + y[2]*z[0];
    x[2] = y[0]*z[1] - y[1]*z[0];

    /* Recompute Y = Z cross X. */
    y[0] = z[1]*x[2] - z[2]*x[1];
    y[1] = -z[0]*x[2] + z[2]*x[0];
    y[2] = z[0]*x[1] - z[1]*x[0];

    /* Normalize X. */
    mag = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
    if (mag) {
    x[0] /= mag;
    x[1] /= mag;
    x[2] /= mag;
    }

    /* Normalize Y. */
    mag = sqrt(y[0]*y[0] + y[1]*y[1] + y[2]*y[2]);
    if (mag) {
    y[0] /= mag;
    y[1] /= mag;
    y[2] /= mag;
    }

    /* Build resulting view matrix. */
    m[0*4+0] = x[0]; m[0*4+1] = x[1];
    m[0*4+2] = x[2]; m[0*4+3] = -x[0]*eyex + -x[1]*eyey + -x[2]*eyez;
    m[1*4+0] = y[0]; m[1*4+1] = y[1];
    m[1*4+2] = y[2]; m[1*4+3] = -y[0]*eyex + -y[1]*eyey + -y[2]*eyez;
    m[2*4+0] = z[0]; m[2*4+1] = z[1];
    m[2*4+2] = z[2]; m[2*4+3] = -z[0]*eyex + -z[1]*eyey + -z[2]*eyez;
    m[3*4+0] = 0.0; m[3*4+1] = 0.0; m[3*4+2] = 0.0; m[3*4+3] = 1.0;
    }

    2           创建模型矩阵modelMatrix 

      /* modelView = rotateMatrix * translateMatrix */

    makeRotateMatrix(70, 1, 1, 1, rotateMatrix);

    makeTranslateMatrix(2, 0, 0, translateMatrix);

    multMatrix(modelMatrix, translateMatrix, rotateMatrix);

     Opengl中设置模型方位和位置.Ogre中自己获取参数.该矩阵即model到世界空间的变换矩阵.

    //makeRotateMatrix实现

    View Code
    /* Build a row-major (C-style) 4x4 matrix transform based on the
    parameters for glRotatef.
    */
    static void makeRotateMatrix(float angle,
    float ax, float ay, float az,
    float m[16])
    {
    float radians, sine, cosine, ab, bc, ca, tx, ty, tz;
    float axis[3];
    axis[0] = ax;
    axis[1] = ay;
    axis[2] = az;

    normalizeVector(axis);

    radians = angle * myPi / 180.0;
    sine = sin(radians);
    cosine = cos(radians);

    ab = axis[0] * axis[1] * (1 - cosine);
    bc = axis[1] * axis[2] * (1 - cosine);
    ca = axis[2] * axis[0] * (1 - cosine);
    tx = axis[0] * axis[0];
    ty = axis[1] * axis[1];
    tz = axis[2] * axis[2];

    m[0] = tx + cosine * (1 - tx);
    m[1] = ab + axis[2] * sine;
    m[2] = ca - axis[1] * sine;
    m[3] = 0.0f;
    m[4] = ab - axis[2] * sine;
    m[5] = ty + cosine * (1 - ty);
    m[6] = bc + axis[0] * sine;
    m[7] = 0.0f;
    m[8] = ca + axis[1] * sine;
    m[9] = bc - axis[0] * sine;
    m[10] = tz + cosine * (1 - tz);
    m[11] = 0;
    m[12] = 0;
    m[13] = 0;
    m[14] = 0;
    m[15] = 1;
    }

    //makeTranslateMatrix实现

    View Code
    /* Build a row-major (C-style) 4x4 matrix transform based on the
    parameters for glTranslatef.
    */
    static void makeTranslateMatrix(float x, float y, float z, float m[16])
    {
    m[0] = 1; m[1] = 0; m[2] = 0; m[3] = x;
    m[4] = 0; m[5] = 1; m[6] = 0; m[7] = y;
    m[8] = 0; m[9] = 0; m[10] = 1; m[11] = z;
    m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
    }

     //multMatrix实现

    View Code
    /* Simple 4x4 matrix by 4x4 matrix multiply. */
    static void multMatrix(float dst[16],
    const float src1[16], const float src2[16])
    {
    float tmp[16];
    int i, j;

    for (i=0; i<4; i++) {
    for (j=0; j<4; j++) {
    tmp[i*4+j] = src1[i*4+0] * src2[0*4+j] +
    src1[i*4+1] * src2[1*4+j] +
    src1[i*4+2] * src2[2*4+j] +
    src1[i*4+3] * src2[3*4+j];
    }
    }

    /* Copy result to dst (so dst can also be src1 or src2). */
    for (i=0; i<16; i++)
    dst[i] = tmp[i];
    }

    3           建立光源到model空间的变换矩阵 

      /* invModelMatrix = inverse(modelMatrix) */
    invertMatrix(invModelMatrix, modelMatrix);

    /* Transform world-space light positions to sphere's object-space. */
    transform(objSpaceLightPosition, invModelMatrix, lightPosition);
    cgSetParameter3fv(myCgVertexParam_lightPosition, objSpaceLightPosition);

    实际上既是求modelMatrix的逆矩阵.然后将光源位置(或投影视点)转换到model空间.
    //invertMatrix

    View Code
    /* Invert a row-major (C-style) 4x4 matrix. */
    static void invertMatrix(float *out, const float *m)
    {
    /* Assumes matrices are ROW major. */
    #define SWAP_ROWS(a, b) { GLdouble *_tmp = a; (a)=(b); (b)=_tmp; }
    #define MAT(m,r,c) (m)[(r)*4+(c)]

    double wtmp[4][8];
    double m0, m1, m2, m3, s;
    double *r0, *r1, *r2, *r3;

    r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];

    r0[0] = MAT(m,0,0), r0[1] = MAT(m,0,1),
    r0[2] = MAT(m,0,2), r0[3] = MAT(m,0,3),
    r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0,

    r1[0] = MAT(m,1,0), r1[1] = MAT(m,1,1),
    r1[2] = MAT(m,1,2), r1[3] = MAT(m,1,3),
    r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0,

    r2[0] = MAT(m,2,0), r2[1] = MAT(m,2,1),
    r2[2] = MAT(m,2,2), r2[3] = MAT(m,2,3),
    r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0,

    r3[0] = MAT(m,3,0), r3[1] = MAT(m,3,1),
    r3[2] = MAT(m,3,2), r3[3] = MAT(m,3,3),
    r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0;

    /* Choose myPivot, or die. */
    if (fabs(r3[0])>fabs(r2[0])) SWAP_ROWS(r3, r2);
    if (fabs(r2[0])>fabs(r1[0])) SWAP_ROWS(r2, r1);
    if (fabs(r1[0])>fabs(r0[0])) SWAP_ROWS(r1, r0);
    if (0.0 == r0[0]) {
    assert(!"could not invert matrix");
    }

    /* Eliminate first variable. */
    m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0];
    s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s;
    s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s;
    s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s;
    s = r0[4];
    if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; }
    s = r0[5];
    if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; }
    s = r0[6];
    if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; }
    s = r0[7];
    if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; }

    /* Choose myPivot, or die. */
    if (fabs(r3[1])>fabs(r2[1])) SWAP_ROWS(r3, r2);
    if (fabs(r2[1])>fabs(r1[1])) SWAP_ROWS(r2, r1);
    if (0.0 == r1[1]) {
    assert(!"could not invert matrix");
    }

    //transform实现

    View Code
    /* Simple 4x4 matrix by 4-component column vector multiply. */
    static void transform(float dst[4],
    const float mat[16], const float vec[4])
    {
    double tmp[4], invW;
    int i;

    for (i=0; i<4; i++) {
    tmp[i] = mat[i*4+0] * vec[0] +
    mat[i*4+1] * vec[1] +
    mat[i*4+2] * vec[2] +
    mat[i*4+3] * vec[3];
    }
    invW = 1 / tmp[3];
    /* Apply perspective divide and copy to dst (so dst can vec). */
    for (i=0; i<3; i++)
    dst[i] = tmp[i] * invW;
    dst[3] = 1;
    }

    4           创建模型视点矩阵

      /* modelViewMatrix = eyeViewMatrix * modelMatrix */
    multMatrix(modelViewMatrix, eyeViewMatrix, modelMatrix);

     model到视点空间的变换矩阵.

    5           创建模型视点投影矩阵

      /* modelViewProj = projectionMatrix * modelViewMatrix */
    multMatrix(modelViewProjMatrix, projectionMatrix, modelViewMatrix);

    projectionMatrix根据以下参数确定:视点空间变换到投影空间的变换矩阵.该步骤与纹理投影无关.

    fieldOfView(FOV):视角大小;

    aspectRatio(aspect):长宽比

    zNear(near):近裁剪面

    zFar(far):远裁剪面

     

    //buildPerspectiveMatrix实现

    View Code
    /* Build a row-major (C-style) 4x4 matrix transform based on the
    parameters for gluPerspective.
    */
    static void buildPerspectiveMatrix(double fieldOfView,
    double aspectRatio,
    double zNear, double zFar,
    float m[16])
    {
    double sine, cotangent, deltaZ;
    double radians = fieldOfView / 2.0 * myPi / 180.0;

    deltaZ = zFar - zNear;
    sine = sin(radians);
    /* Should be non-zero to avoid division by zero. */
    assert(deltaZ);
    assert(sine);
    assert(aspectRatio);
    cotangent = cos(radians) / sine;

    m[0*4+0] = cotangent / aspectRatio;
    m[0*4+1] = 0.0;
    m[0*4+2] = 0.0;
    m[0*4+3] = 0.0;

    m[1*4+0] = 0.0;
    m[1*4+1] = cotangent;
    m[1*4+2] = 0.0;
    m[1*4+3] = 0.0;

    m[2*4+0] = 0.0;
    m[2*4+1] = 0.0;
    m[2*4+2] = -(zFar + zNear) / deltaZ;
    m[2*4+3] = -2 * zNear * zFar / deltaZ;

    m[3*4+0] = 0.0;
    m[3*4+1] = 0.0;
    m[3*4+2] = -1;
    m[3*4+3] = 0;
    }

    6           创建纹理投影矩阵

    buildTextureMatrix(lightViewMatrix, modelMatrix, /*out*/textureMatrix);

    /* Set matrix parameter with row-major matrix. */
    cgSetMatrixParameterfr(myCgVertexParam_modelViewProj, modelViewProjMatrix);
    cgSetMatrixParameterfr(myCgVertexParam_textureMatrix, textureMatrix);

    static void buildTextureMatrix(const float viewMatrix[16],
    const float modelMatrix[16],
    float textureMatrix[16])
    {
    static float eyeToClipMatrix[16];
    float modelViewMatrix[16];
    static int needsInit = 1;

    if (needsInit) {
    const float fieldOfView = 50.0f;
    const float aspectRatio = 1;
    float textureProjectionMatrix[16];
    float clipToTextureMatrix[16];

    /* Build texture projection matrix once. */
    buildPerspectiveMatrix(fieldOfView, aspectRatio,
    0.25, 20.0, /* Znear and Zfar */
    textureProjectionMatrix);

    makeClipToTextureMatrix(clipToTextureMatrix);

    /* eyeToClip = clipToTexture * textureProjection */
    multMatrix(eyeToClipMatrix,
    clipToTextureMatrix, textureProjectionMatrix);
    needsInit = 1;
    }

    /* modelView = view * model */
    multMatrix(modelViewMatrix, viewMatrix, modelMatrix);
    /* texture = eyeToClip * modelView */
    multMatrix(textureMatrix, eyeToClipMatrix, modelViewMatrix);
    }

    该函数中:

    1>     buildPerspectiveMatrix同前面的,不过这里用来计算用于投影纹理的视景体变换(投影变换).

    2>     makeClipToTextureMatrix(clipToTextureMatrix)建立视景体裁切矩阵.

    因为视景体是长度为1的单位空间.

    3>     将1, 2步的矩阵相乘:    multMatrix(eyeToClipMatrix,clipToTextureMatrix,textureProjectionMatrix);

    eyeToClipMatrix为得到的纹理投影裁剪变换矩阵.

    4>     multMatrix(modelViewMatrix, viewMatrix, modelMatrix);

    modelViewMatrix为从模型空间到光源(投影视点)空间的变换矩阵.

    5>     将3, 4步的结果相乘:

    multMatrix(textureMatrix, eyeToClipMatrix, modelViewMatrix);

    textureMatrix为从模型视点空间(基于光源位置或投影视点)到纹理投影裁剪空间的变换矩阵.

    textureMatrix此即最终的纹理投影变换矩阵.从这些流程可以明白,实际上是把模型投影到纹理上.

    顶点程序:

    void C9E5v_projTex(float4 position : POSITION,
    float3 normal : NORMAL,

    out float4 oPosition : POSITION,
    out float4 texCoordProj : TEXCOORD0,
    out float4 diffuseLighting : COLOR,

    uniform float Kd,
    uniform float4x4 modelViewProj,
    uniform float3 lightPosition,
    uniform float4x4 textureMatrix)
    {
    oPosition = mul(modelViewProj, position);

    // Compute texture coordinates for
    // querying the projective texture
    texCoordProj = mul(textureMatrix, position);

    // Compute diffuse lighting
    float3 N = normalize(normal);
    float3 L = normalize(lightPosition - position.xyz);
    diffuseLighting = Kd * max(dot(N, L), 0);
    }

    片段程序:

    void C9E6f_projTex(float4 texCoordProj    : TEXCOORD0,
    float4 diffuseLighting : COLOR,

    out float4 color : COLOR,

    uniform sampler2D projectiveMap)
    {
    // Fetch color from the projective texture
    float4 textureColor = tex2Dproj(projectiveMap,
    texCoordProj);

    color = textureColor * diffuseLighting;
    }




  • 相关阅读:
    A Complete Guide to the <Picture> Element
    html5 在移动端的缩放控制
    新版itunes添加铃声
    html5 背景音乐 js控制播放 暂停
    thinkphp mysql 坐标按距离排序
    jquery ajax跨域 thinkphp getjson
    webkit-box
    Javascript 获取页面高度(多种浏览器)
    怎样实现iMessage群发
    css3背景透明文字不透明
  • 原文地址:https://www.cnblogs.com/flytrace/p/2236199.html
Copyright © 2020-2023  润新知