cg toolkit中關於紋理投影的例子

紋理投影流程

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實現
複製代碼
/* 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實現

複製代碼
/* 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實現

複製代碼
/* 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 

 

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

複製代碼
/* 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實現

複製代碼
/* 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 

 

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;
}   
複製代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章