   Direct3D port of OpenGL code issue
  Hello All,I've been trying to write a Direct3D port of an openGL function that generates an ambient lightmap; the OpenGL code is shown in the following box:#define AMBIENT_RESOLUTION 16void GLRenderPath::makeAmbientMap() {  glGenTextures(1, &ambientMap);  glMatrixMode(GL_PROJECTION);  glPushMatrix();  gluPerspective(90.0f, 1.0f, *znear, *viewDistance);  glMatrixMode(GL_MODELVIEW);  glPushMatrix();  glLoadIdentity();  glGetIntegerv(GL_VIEWPORT, viewPort);  glViewport(0,0, AMBIENT_RESOLUTION, AMBIENT_RESOLUTION);  float fcol[6][3];  float tcol[6][3];  enum {PX = 0,NX,PY,NY,PZ,NZ  };  float rp[] = {    90, 0, 1, 0,   -90, 0, 1, 0,   -90, 1, 0, 0,    90, 1, 0, 0,    180, 0, 1, 0,    0, 0, 1, 0  };  float rv[] = {    1, 0, 0,   -1, 0, 0,    0, 1, 0,    0, -1, 0,    0, 0, 1,    0, 0, -1  };  for (int i = 0; i < 6; i++) {    glPushMatrix();    if (i != 2 && i != 3 ) {  glRotatef(180, 0, 0, 1);    }    glRotatef(rp[i*4], rp[i*4+1], rp[i*4+2], rp[i*4+3]);    drawSkyBox();    float s[AMBIENT_RESOLUTION*AMBIENT_RESOLUTION*3];    glReadPixels(0,   0,   AMBIENT_RESOLUTION,   AMBIENT_RESOLUTION,   GL_RGB,   GL_FLOAT,   s);    //calculate median    float m[3];    m[0] = 0;    m[1] = 0;    m[2] = 0;    for (int j = 0; j < AMBIENT_RESOLUTION; j++) { for (int k = 0; k < AMBIENT_RESOLUTION; k++) {   for (int l = 0; l < 3; l++) {   m[l] += s[(j*AMBIENT_RESOLUTION+k)*3+l];} }    }    for (int l = 0; l < 3; l++) { m[l] /= AMBIENT_RESOLUTION*AMBIENT_RESOLUTION; tcol[l] = m[l];    }    //scale(tcol, 0.75f);    glPopMatrix();  }  //do some HDRish nonsense on the faces of the cubemap  float m;  float mx = 0;  float mn = 100;  for (GLuint k = 0; k < 2; k++) {m = 0;for (GLuint i = 0; i < 6; i++) {   for (GLuint j = 0; j < 3; j++) {  fcol[j] = (tcol[j]*2 +tcol[(j+1)%3] +tcol[(j+2)%3])*0.25f;}m += magnitude(fcol);if (m > mx)   mx = m;if (m < mn)   mn = m;}  }  m /= 6.0f;  float r = (mx-mn);  if (r >= 0.001f) {    for (GLuint i = 0; i < 6; i++) { float sc = (magnitude(fcol)-m)*16.0f/r + 1; scale(fcol, sc);    }  }  for (GLuint i = 0; i < 6; i++) {    //calculate cube map face    //for each corner of the face,//the color value is this face averaged with the two    //neighboring facesfloat a[12];    switch (GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i) { case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: { for (int j = 0; j < 3; j++) {//top right  a[j] = (fcol[j] + fcol[PY][j] + fcol[PZ][j]) / 3.0f; //top left  a[j+3] = (fcol[j] + fcol[PY][j] + fcol[NZ][j]) / 3.0f;//bottom right 1  a[j+6] = (fcol[j] + fcol[NY][j] + fcol[PZ][j]) / 3.0f;//bottom left  a[j+9] = (fcol[j] + fcol[NY][j] + fcol[NZ][j]) / 3.0f;   }break;  }  case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: {   for (int j = 0; j < 3; j++) {//top right  a[j] =   (fcol[j] + fcol[PY][j] + fcol[NZ][j]) / 3.0f;   //top left  a[j+3] = (fcol[j] + fcol[PY][j] + fcol[PZ][j]) / 3.0f;//bottom right  a[j+6] = (fcol[j] + fcol[NY][j] + fcol[NZ][j]) / 3.0f;//bottom left  a[j+9] = (fcol[j] + fcol[NY][j] + fcol[PZ][j]) / 3.0f;}break;  } case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: {    for (int j = 0; j < 3; j++) {  //front left    a[j] = (fcol[j] + fcol[NX][j] + fcol[NZ][j]) / 3.0f;  //front righta[j+3] = (fcol[j] + fcol[PX][j] + fcol[NZ][j]) / 3.0f;  //back left    a[j+6] = (fcol[j] + fcol[NX][j] + fcol[PZ][j]) / 3.0f;  //back right    a[j+9] = (fcol[j] + fcol[PX][j] + fcol[PZ][j]) / 3.0f; } break; }case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: {for (int j = 0; j < 3; j++) { //back left   a[j] = (fcol[j] + fcol[NX][j] + fcol[PZ][j]) / 3.0f;    //back right   a[j+3] = (fcol[j] + fcol[PX][j] + fcol[PZ][j]) / 3.0f; //front left   a[j+6] = (fcol[j] + fcol[NX][j] + fcol[NZ][j]) / 3.0f; //front right   a[j+9] = (fcol[j] + fcol[PX][j] + fcol[NZ][j]) / 3.0f;   }break;}case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: {   for (int j = 0; j < 3; j++) {//top right  a[j] = (fcol[j] + fcol[NX][j] + fcol[PY][j]) / 3.0f; //top left 2  a[j+3] = (fcol[j] + fcol[PX][j] + fcol[PY][j]) / 3.0f;//bottom right  a[j+6] = (fcol[j] + fcol[NX][j] + fcol[NY][j]) / 3.0f;//bottom left 1  a[j+9] = (fcol[j] + fcol[PX][j] + fcol[NY][j]) / 3.0f;}break;}    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: {  for (int j = 0; j < 3; j++) {    //top right    a[j] = (fcol[j] + fcol[PX][j] + fcol[PY][j]) / 3.0f;  //top left a[j+3] = (fcol[j] + fcol[NX][j] + fcol[PY][j]) / 3.0f; //bottom right a[j+6] = (fcol[j] + fcol[PX][j] + fcol[NY][j]) / 3.0f; //bottom left a[j+9] = (fcol[j] + fcol[NX][j] + fcol[NY][j]) / 3.0f; }   }  } //end switch  glEnable(GL_TEXTURE_CUBE_MAP_ARB);  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);  glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, ambientMap);  glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_GENERATE_MIPMAP_SGIS, GL_FALSE);  glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);  glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);  glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, GL_RGB, 2, 2, 0,    GL_RGB, GL_FLOAT, a);  glPopMatrix(); }  glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glDisable(GL_TEXTURE_CUBE_MAP_ARB); glEnable(GL_TEXTURE_2D); glViewport(0, 0, viewPort[2], viewPort[3]); //DEBUG: set skybox to ambient map so we can see the resulting lightmap //when it gets rendered environmentMap = ambientMap;}Basically the function uses an HDR algorithm to generate a lightmap given the faces of skybox. Please note that I did not write the OpenGL version of this code. This was the work of someone far more brilliant in the field of graphics programming than I. I'm simply trying to port this code over to Direct3D for a larger scale project I'm working on. One of my many attempts at porting this complex code to Direct3D is listed in the following code box:#define AMBIENT_RESOLUTION 16void DXRenderPath::makeAmbientMap() {  //generate memory for cube map  HRESULT res = D3DXCreateCubeTexture(deviceHandle, 2, 0, D3DUSAGE_DYNAMIC, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &ambientMap);  //save old project, view, and viewport matrices  D3DXMATRIX projOld;  D3DXMATRIX viewOld;  D3DVIEWPORT9 viewportOld;  deviceHandle->GetTransform(D3DTS_PROJECTION,&projOld);  deviceHandle->GetTransform(D3DTS_VIEW,&viewOld);  deviceHandle->GetViewport(&viewportOld);  //set new projection  D3DXMATRIX projNew;  D3DXMatrixPerspectiveFovLH(&projNew,// result3.14159f/2.0f,// fov1.0,// aspect ratioZNEAR,// near planeVIEW_DIST);// far plane  deviceHandle->SetTransform(D3DTS_PROJECTION,&projNew);  //set new viewport  D3DVIEWPORT9 viewportNew;  viewportNew.X = 0;  viewportNew.Y = 0;  viewportNew.Width = AMBIENT_RESOLUTION;  viewportNew.Height = AMBIENT_RESOLUTION;  deviceHandle->SetViewport(&viewportNew);  float fcol[6][3];  float tcol[6][3];  enum {PX = 0,NX,PY,NY,PZ,NZ  };  for (int i = 0; i < 6; i++)   {//switch view as per faceD3DXVECTOR3 vEnvEyePt(0.0f, 0.0f, 0.0f);D3DXVECTOR3 vLookatPt, vUpVec;switch(i){   case D3DCUBEMAP_FACE_POSITIVE_X:vLookatPt = D3DXVECTOR3(1.0f, 0.0f, 0.0f);vUpVec = D3DXVECTOR3(0.0f, 1.0f, 0.0f);break;   case D3DCUBEMAP_FACE_NEGATIVE_X:vLookatPt = D3DXVECTOR3(-1.0f, 0.0f, 0.0f);vUpVec = D3DXVECTOR3( 0.0f, 1.0f, 0.0f);break;   case D3DCUBEMAP_FACE_POSITIVE_Y:vLookatPt = D3DXVECTOR3(0.0f, 1.0f, 0.0f);vUpVec = D3DXVECTOR3(0.0f, 0.0f,-1.0f);break;   case D3DCUBEMAP_FACE_NEGATIVE_Y:vLookatPt = D3DXVECTOR3(0.0f,-1.0f, 0.0f);vUpVec = D3DXVECTOR3(0.0f, 0.0f, 1.0f);break;   case D3DCUBEMAP_FACE_POSITIVE_Z:vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 1.0f);vUpVec = D3DXVECTOR3( 0.0f, 1.0f, 0.0f);break;   case D3DCUBEMAP_FACE_NEGATIVE_Z:vLookatPt = D3DXVECTOR3(0.0f, 0.0f,-1.0f);vUpVec = D3DXVECTOR3(0.0f, 1.0f, 0.0f);break;    }    D3DXMATRIX matView;    D3DXMatrixLookAtLH(&matView, &vEnvEyePt, &vLookatPt, &vUpVec);    deviceHandle->SetTransform(D3DTS_VIEW, &matView);    //draw contents of skybox into smaller sample of pixel buffer    deviceHandle->BeginScene();    drawSkyBox();    deviceHandle->EndScene();    //read data from smaller area of pixel buffer (probably wrong)    //glReadPixels(0, 0, AMBIENT_RESOLUTION, AMBIENT_RESOLUTION, GL_RGB, GL_FLOAT, s);    float s[AMBIENT_RESOLUTION*AMBIENT_RESOLUTION*3];    LPDIRECT3DSURFACE9 targSurf = NULL;    HRESULT res = deviceHandle->GetRenderTarget(0,&targSurf);LPDIRECT3DSURFACE9 tmpSurface;    deviceHandle->CreateOffscreenPlainSurface(AMBIENT_RESOLUTION, AMBIENT_RESOLUTION,  D3DFMT_A32B32G32R32F, D3DPOOL_SYSTEMMEM,  &tmpSurface, NULL);    RECT r;    r.left = 0;    r.top = 0;    r.bottom = AMBIENT_RESOLUTION;    r.right = AMBIENT_RESOLUTION;    //should copy surface data from surface of screen buffer to our surface    //with conversion of data to floating point (I think)    res = D3DXLoadSurfaceFromSurface(tmpSurface,   NULL,   NULL,   targSurf,   NULL,   &r,   D3DX_DEFAULT,   0);    D3DLOCKED_RECT lrect;    res = tmpSurface->LockRect( &lrect, NULL, 0 );    void * pBits = lrect.pBits;    INT Pitch = lrect.Pitch;    //copy pixels from surface into float array (probably wrong)    unsigned char BytesPerPixel1 = 4*sizeof( float );    unsigned int index = 0;    char buf2[255];    for(int Y = 0; Y < AMBIENT_RESOLUTION; Y++)    { for(int X = 0; X < AMBIENT_RESOLUTION; X++) {unsigned char* pPixelAddress1 =  ( (unsigned char*)pBits ) + (Y * Pitch) + (X * BytesPerPixel1);memcpy(&(s[index]),(pPixelAddress1),sizeof(float)*3);index += 3;    }    tmpSurface->UnlockRect();    tmpSurface->Release();    targSurf->Release();    //calculate median    float m[3];    m[0] = 0;    m[1] = 0;    m[2] = 0;    for (int j = 0; j < AMBIENT_RESOLUTION; j++) { for (int k = 0; k < AMBIENT_RESOLUTION; k++) {   for (int l = 0; l < 3; l++) {  int val = (j*AMBIENT_RESOLUTION+k)*3+l;  m[l] += s[val];} }    }    for (int l = 0; l < 3; l++) { m[l] /= AMBIENT_RESOLUTION*AMBIENT_RESOLUTION; tcol[l] = m[l];    }  }  //do some HDRish nonsense on the faces of the cubemap  float m;  float mx = 0;  float mn = 100;  for (unsigned int k = 0; k < 2; k++) {    m = 0;    for (unsigned int i = 0; i < 6; i++) { for (unsigned int j = 0; j < 3; j++) {   fcol[j] = (tcol[j]*2 +   tcol[(j+1)%3] + tcol[(j+2)%3])*0.25f; } m += magnitude(fcol); if (m > mx)    mx = m; if (m < mn) mn = m;    }  }  m /= 6.0f;  float r = (mx-mn);  if (r >= 0.001f) {    for (unsigned int i = 0; i < 6; i++) { float sc = (magnitude(fcol)-m)*16.0f/r + 1; scale(fcol, sc);    }  }  for (unsigned int i = 0; i < 6; i++) {    //calculate cube map face    //for each corner of the face, the color value is this face//averaged with the two neighboring facesfloat a[12];    memset( a , 0.0f , sizeof(float)*12 );    switch (D3DCUBEMAP_FACE_POSITIVE_X+i) { case D3DCUBEMAP_FACE_POSITIVE_X: {   for (int j = 0; j < 3; j++) {//top left  a[j] =   (fcol[j] + fcol[PY][j] + fcol[PZ][j]) / 3.0f;//top right   a[j+3] = (fcol[j] + fcol[PY][j] + fcol[NZ][j]) / 3.0f;//bottom left  a[j+6] = (fcol[j] + fcol[NY][j] + fcol[PZ][j]) / 3.0f;//bottom right 1   a[j+9] = (fcol[j] + fcol[NY][j] + fcol[NZ][j]) / 3.0f;}break;  }  case D3DCUBEMAP_FACE_NEGATIVE_X: {for (int j = 0; j < 3; j++) { //top left   a[j] = (fcol[j] + fcol[PY][j] + fcol[NZ][j]) / 3.0f; //top right   a[j+3] =   (fcol[j] + fcol[PY][j] + fcol[PZ][j]) / 3.0f; //bottom left   a[j+6] = (fcol[j] + fcol[NY][j] + fcol[NZ][j]) / 3.0f; //bottom right    a[j+9] = (fcol[j] + fcol[NY][j] + fcol[PZ][j]) / 3.0f;}break;  } case D3DCUBEMAP_FACE_POSITIVE_Y: {    for (int j = 0; j < 3; j++) { //back left   a[j] = (fcol[j] + fcol[NX][j] + fcol[NZ][j]) / 3.0f; //back right   a[j+3] = (fcol[j] + fcol[PX][j] + fcol[NZ][j]) / 3.0f; //front left   a[j+6] =   (fcol[j] + fcol[NX][j] + fcol[PZ][j]) / 3.0f;  //front right   a[j+9] = (fcol[j] + fcol[PX][j] + fcol[PZ][j]) / 3.0f; } break;  } case D3DCUBEMAP_FACE_NEGATIVE_Y: { for (int j = 0; j < 3; j++) {  //back left  a[j] = (fcol[j] + fcol[NX][j] + fcol[PZ][j]) / 3.0f; //back right  a[j+3] = (fcol[j] + fcol[PX][j] + fcol[PZ][j]) / 3.0f;//front left  a[j+6] = (fcol[j] + fcol[NX][j] + fcol[NZ][j]) / 3.0f;//front right  a[j+9] = (fcol[j] + fcol[PX][j] + fcol[NZ][j]) / 3.0f; } break; } case D3DCUBEMAP_FACE_POSITIVE_Z: { for (int j = 0; j < 3; j++) {//top left 2  a[j] = (fcol[j] + fcol[NX][j] + fcol[PY][j]) / 3.0f;//top right  a[j+3] = (fcol[j] + fcol[PX][j] + fcol[PY][j]) / 3.0f;//bottom left 1   a[j+6] = (fcol[j] + fcol[NX][j] + fcol[NY][j]) / 3.0f;//bottom right  a[j+9] = (fcol[j] + fcol[PX][j] + fcol[NY][j]) / 3.0f; } break;  } case D3DCUBEMAP_FACE_NEGATIVE_Z: {   for (int j = 0; j < 3; j++) {//top left  a[j] = (fcol[j] + fcol[PX][j] + fcol[PY][j]) / 3.0f;//top right  a[j+3] = (fcol[j] + fcol[NX][j] + fcol[PY][j]) / 3.0f;//bottom left   a[j+6] = (fcol[j] + fcol[PX][j] + fcol[NY][j]) / 3.0f;//bottom right  a[j+9] = (fcol[j] + fcol[NX][j] + fcol[NY][j]) / 3.0f;} }    } //end switch    //copy pixel data into next face of cube map (probably wrong)    //glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+i, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_FLOAT, a);    D3DLOCKED_RECT texCubeData;    res = ambientMap->LockRect((_D3DCUBEMAP_FACES )i,0,&texCubeData,NULL,0);    void * pBits1 = texCubeData.pBits;    INT Pitch1 = texCubeData.Pitch;    int offset = 0;    unsigned char ComponentsPerPixel1 = 4*sizeof(float);    for(int Y = 0; Y < 2; Y++)    { for(int X = 0; X < 2; X++) {   unsigned char * pPixelAddress1 =((unsigned char*)pBits1 ) + (Y * Pitch1) + (X * ComponentsPerPixel1);    memcpy(pPixelAddress1,&(a[offset]),sizeof(float)*3); ((float*)pPixelAddress1)[3] = 1.0f; offset += 3; }    }    res = ambientMap->UnlockRect((_D3DCUBEMAP_FACES)   (D3DCUBEMAP_FACE_POSITIVE_X+i),   0);  }  //restore original matrices  deviceHandle->SetTransform(D3DTS_VIEW, &viewOld );  deviceHandle->SetTransform(D3DTS_PROJECTION,&projOld);  deviceHandle->SetViewport(&viewportOld);  //DEBUG: set skybox to ambient map so we can see the resulting lightmap  //when it gets rendered  envMap = ambientMap;}The Direct3D port is a complete disaster as the resulting lightmap ends up looking nothing like the openGL one. The following link shows an image of what one of the resulting faces of the ambient map looks like in openGL:http://www.rit.edu/~axv4745/muppetsDX/GLlightMap.jpgIf you moved around with the camera you'd that its a smooth cube map with a nice high range of black and white colorsThis link shows what the Direct3D one looks like:http://www.rit.edu/~axv4745/muppetsDX/D3DlightMap.jpgPlease note that the image of Direct3D texture is the same dimensions as the openGL but since the webpages are white you'll only notice the black. Its actually a half black half white texture. But as you can see the colors are completely flat and if you moved around the cube with the camera you'd see its completelely flat shaded all around the cube.I've pretty much tried to take everything into account in my Direct3D port (e.g. differences in bit-byte ordering of textures, orientation of UV coordinates, etc...) and it seems like nothing I do will make the Direct3D ambient lightmap  look even remotely close to the openGL map (I can't even get the map to be smooth shaded with a high range of colors).I even did a complete dump of of all the pixel values (as unsigned bytes and as floats) to compare and contrast the Direct3D and GL versions and the values were reasonably sane (the values were not exactly the same between Direct3D and GL but I could clearly see that the conversions were correct given the API I was using)Here are links to the resulting frame buffer pixel data for the given faces of the cube map:http://www.rit.edu/~axv4745/muppetsDX/d3d.txthttp://www.rit.edu/~axv4745/muppetsDX/gl.txtLike I mentioned they are not quite the same but they aren't that different such that you'd a substantial difference when you rendered it to the screen. I even tried hardcoding the pixel values of the Direct3D map to be those of the OpenGL map and the map still ended up looking flat shaded. Similarly I tried hardcoding the pixel values of the OpenGL map to be those of the Direct3D map and it still looked smooth shaded with a high range of black and white values (granted it looked different since I was using different pixel values)I almost feel that a Direct3D port of the given openGL code is just not possible but I figured I would put a post on the forums to see if anybody could offer some insight/ideas as to where I am messing. The code I've just provided is pretty complex and I don't expect that anyone would be able to quickly figure whats wrong. But if anyone is willing to take some time to look at my Direct3D port code and perhaps provide some insight as to whats going wrong, I would be hightly appreciativeThanks in advance,[Edited by - axv4745 on July 11, 2006 9:38:28 PM]