Results 11 to 18 of 18

Thread: Normal mapping

Threaded View

Previous Post Previous Post   Next Post Next Post
  1. #1

    Normal mapping

    Has anyone done a simple demo about normal mapping with OpenGL? All it would need to do is draw a cube, using texture and normalmap texture, as a bonus even a specular map texture.

    It would be nice if it's possible without getting into pixel-shaders, but i know there are some demos using GL_ARB_multitexture. I have looked up some C sources but just can't get it working. Must be missing some detail. Best i have come up with is like in attached screenshot (you can see that it's actually just drawing the normal map, instead of using it for lighting, which in itself goes wrong).

    Also, i am aware there are 2 different kinds of normal maps. One where it multiplies the normalmap with models own face normals, and one where normalmap is the only thing used for lighting calculation. I'm actually more interested in the latter, because it would mean less memory use if i don't need vector arrays for normals.

    Well, i can give some converted code which has propably ton of bugs (it's fit for nxPascal engine):
    Code:
        model: TGLModel;
        texture, normalMap, cubemap: cardinal;
        dl: TDisplayList;
        tangentSpaceLight: array of TVector;
        sTangent, tTangent, normal: array of TVector;
    Code:
    procedure GenerateNormalisationCubeMap;
    var size: integer; offset, halfSize: single; data: array of byte;
    
      procedure Generate(arb: byte);
      var i, j, dp: integer; tempVector: TVector;
      begin
        dp:=0;
        for j:=0 to size-1 do
          for i:=0 to size-1 do begin
            case arb of
              0: begin // +X
                   tempVector.x:=halfSize;
                   tempVector.y:=-(j+offset-halfSize);
                   tempVector.z:=-(i+offset-halfSize);
                 end;
              1: begin // -X
                   tempVector.x:=-halfSize;
                   tempVector.y:=-(j+offset-halfSize);
                   tempVector.z:=(i+offset-halfSize);
                 end;
              2: begin // +Y
                   tempVector.x:=(i+offset-halfSize);
                   tempVector.y:=halfSize;
                   tempVector.z:=(j+offset-halfSize);
                 end;
              3: begin // -Y
                   tempVector.x:=(i+offset-halfSize);
                   tempVector.y:=-halfSize;
                   tempVector.z:=-(j+offset-halfSize);
                 end;
              4: begin // +Z
                   tempVector.x:=(i+offset-halfSize);
                   tempVector.y:=-(j+offset-halfSize);
                   tempVector.z:=halfSize;
                 end;
              5: begin // -Z
                   tempVector.x:=-(i+offset-halfSize);
                   tempVector.y:=-(j+offset-halfSize);
                   tempVector.z:=-halfSize;
                 end;
            end;
            tempVector:=Norm2(tempVector);
            tempVector.x:=0.5*tempVector.x+0.5;
            tempVector.y:=0.5*tempVector.y+0.5;
            tempVector.z:=0.5*tempVector.z+0.5;
            data[dp]:=round(tempVector.x*255);
            data[dp+1]:=round(tempVector.y*255);
            data[dp+2]:=round(tempVector.z*255);
            inc(dp,3);
          end;
        arb:=GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB+arb;
        glTexImage2D(arb, 0, GL_RGBA8, size, size, 0, GL_RGB,
          GL_UNSIGNED_BYTE, @data[0]);
      end;
    
    var i: integer;
    begin
      size:=32; offset:=0.5; halfSize:=size/2;
      setlength(data, size*size*3);
      for i:=0 to 5 do Generate(i);
    end;
    Code:
    procedure TForm1.FormCreate(Sender: TObject);
    var bmp: TBitmap; i: integer;
    begin
      clientwidth:=800; clientheight:=600;
      nx.CreateGlWindow(self);
      nx.Perspective(false); nx.DefaultLights;
    
      if not nx.GLInfo('GL_ARB_multitexture') then begin
        showmessage('GL_ARB_multitexture not supported!'); exit;
      end;
    
      tex.Options:=tex.Options+[toKeepData];
    
      model:=TGLModel.Create;
      model.LoadFromW3D('data\donut.w3d');
      model.LoadTextures('data');
      texture:=model.mat[0].texIndex;
      model.MakeDisplayList(dl);
      setlength(tangentSpaceLight, model.vCount);
      setlength(sTangent, model.fCount);
      setlength(tTangent, model.fCount);
      setlength(normal, model.fCount);
      for i:=0 to model.fCount-1 do CalculateTangentSpace(i);
    
      bmp:=TBitmap.Create;
      MakeBumpTexture(0, bmp);
     
      normalMap:=tex.AddTexture('bump','');
      tex.LoadBMPData(normalMap, bmp);
      tex.Restore(normalMap);
    
      normalMap:=tex.texture[normalMap].index;
      model.mat[0].texIndex:=normalMap;
      bmp.Free;
    
      cubemap:=tex.AddTexture('_cubemap_','');
      cubemap:=tex.texture[cubemap].index;
      glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, cubemap);
      GenerateNormalisationCubeMap;
      glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
      glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
      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);
      ...
    end;
    Code:
    procedure TForm1.Timer1Timer(Sender: TObject);
    var i, j: integer; objectLightPosition, lightVector: TVector;
    begin
      ...
      objectLightPosition:=vector(0, 5, -10);
    
      for i:=0 to model.fCount-1 do
        for j:=0 to 2 do begin
          lightVector:=VectorSub2(objectLightPosition, model.va[model.fa[i, j]]);
          tangentSpaceLight[model.fa[i, j]].x:=Dot(sTangent[i], lightVector);
          tangentSpaceLight[model.fa[i, j]].y:=Dot(tTangent[i], lightVector);
          tangentSpaceLight[model.fa[i, j]].z:=Dot(normal[i], lightVector);
        end;
      
      //Bind normal map to texture unit 0
      glBindTexture(GL_TEXTURE_2D, normalMap);
      glEnable(GL_TEXTURE_2D);
    
      //Bind normalisation cube map to texture unit 1
      glActiveTextureARB(GL_TEXTURE1_ARB);
      glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, CubeMap);
      glEnable(GL_TEXTURE_CUBE_MAP_ARB);
      glActiveTextureARB(GL_TEXTURE0_ARB);
    
      glVertexPointer(3, GL_FLOAT, 0, @model.va[0]);
      glEnableClientState(GL_VERTEX_ARRAY);
    
      glTexCoordPointer(2, GL_FLOAT, 0, @model.ta[0]);
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
      glClientActiveTextureARB(GL_TEXTURE1_ARB);
      glTexCoordPointer(3, GL_FLOAT, 0, @tangentSpaceLight[0]);
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
      glClientActiveTextureARB(GL_TEXTURE0_ARB);
    
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
      glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
      glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
    
      glActiveTextureARB(GL_TEXTURE1_ARB);
    
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
      glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
      glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);
      glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB);
    
      glActiveTextureARB(GL_TEXTURE0_ARB);
    
      // Render Bumps
      glDrawElements(GL_TRIANGLES, model.fCount*3, GL_UNSIGNED_SHORT, @model.fa[0]);
    
      glDisable(GL_TEXTURE_2D);
    
      glActiveTextureARB(GL_TEXTURE1_ARB);
      glDisable(GL_TEXTURE_CUBE_MAP_ARB);
      glActiveTextureARB(GL_TEXTURE0_ARB);
    
      //disable vertex arrays
      glDisableClientState(GL_VERTEX_ARRAY);
    
      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    
      glClientActiveTextureARB(GL_TEXTURE1_ARB);
      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
      glClientActiveTextureARB(GL_TEXTURE0_ARB);
    
      //Return to standard modulate texenv
      glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    
      //Enable multiplicative blending
      glBlendFunc(GL_DST_COLOR, GL_ZERO);
      glEnable(GL_BLEND);
    
      glBindTexture(GL_TEXTURE_2D, Texture);
      glEnable(GL_TEXTURE_2D);
    
      glVertexPointer(3, GL_FLOAT, 0, @model.va[0]);
      glEnableClientState(GL_VERTEX_ARRAY);
    
      glNormalPointer(GL_FLOAT, 0, @model.va[0]);
      glEnableClientState(GL_NORMAL_ARRAY);
    
      glTexCoordPointer(2, GL_FLOAT, 0, @model.ta[0]);
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
      // Render Object
      glDrawElements(GL_TRIANGLES, model.fCount*3, GL_UNSIGNED_SHORT, @model.fa[0]);
    
      //Disable texture
      glDisable(GL_TEXTURE_2D);
    
      //disable vertex arrays
      glDisableClientState(GL_VERTEX_ARRAY);
      glDisableClientState(GL_NORMAL_ARRAY);
      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    
      //Disable blending if it is enabled
      glDisable(GL_BLEND);
    
      nx.Flip;
    But of course, if this would be simpler or more efficient to do with pixel-shaders, then i will of course try that instead. I just don't know about this topic much.
    Attached Images Attached Images
    Last edited by User137; 14-07-2012 at 04:23 PM.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •