Advertisement Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

178 Neutral

About jpventoso

  • Rank
  1. jpventoso

    lightmap GENERATION CODE

    I used the first link you posted to build my lightmap generator. But I did it in Pascal, if you think you could use my Pascal code I can paste it for you. Regards,
  2. jpventoso

    SSAO and normal buffer

    Or you can use an approach like this one.
  3. jpventoso

    .X file format is a nightmare

    If you want to use a software like 3D Studio and load those models with the LoadModelX() I have an algorithm that converts the .3DS format to the .X format (but it's in Pascal): Header: {==============================================================================} {== 3DS file compatibility ==} {==============================================================================} {== Reads a 3DS file and converts it into a D3DX Mesh object ==} {==============================================================================} const MAX3DS_ID_HEADER = $4D4D; // File header MAX3DS_ID_OBJECTINFO = $3D3D; // Object information MAX3DS_ID_VERSION = $0002; // File version MAX3DS_ID_SCALE = $0100; // Scale MAX3DS_ID_MESH_VERSION = $3D3E; // Mesh version MAX3DS_ID_OBJECT = $4000; // Object MAX3DS_ID_OBJECT_MESH = $4100; // Mesh MAX3DS_ID_OBJECT_VERTICES = $4110; // Mesh vertices MAX3DS_ID_OBJECT_FACES = $4120; // Mesh faces MAX3DS_ID_OBJECT_MATERIAL = $4130; // Mesh material MAX3DS_ID_OBJECT_UV = $4140; // Mesh texture coords MAX3DS_ID_OBJECT_MATRIX = $4160; // Object transform MAX3DS_ID_OBJECT_PIVOT = $B020; // Object pivot MAX3DS_ID_LIGHT = $4600; // Scene light MAX3DS_ID_CAMERA = $4700; // Camera information MAX3DS_ID_MATERIAL = $AFFF; // Material information MAX3DS_ID_KEYFRAME = $B000; // Keyframe MAX3DS_ID_KEYFRAME_OBJECT = $B002; // Keyframe object MAX3DS_ID_COLOR = $0010; // Color MAX3DS_ID_LIGHT_RANGE = $465A; // Light range MAX3DS_MAXVERTICES = 65536; // Max vertices // 3DS loaded object vertex declaration (float3 POSITION, float2 TEXCOORD0) Tz3D3DSObjectVD: array [0..2] of TD3DVertexElement9 = ( (Stream: 0; Offset: 0; _Type: D3DDECLTYPE_FLOAT3; Method: D3DDECLMETHOD_DEFAULT; Usage: D3DDECLUSAGE_POSITION; UsageIndex: 0), (Stream: 0; Offset: 12; _Type: D3DDECLTYPE_FLOAT2; Method: D3DDECLMETHOD_DEFAULT; Usage: D3DDECLUSAGE_TEXCOORD; UsageIndex: 0), (Stream: $FF; Offset: 0; _Type: D3DDECLTYPE_UNUSED; Method: TD3DDeclMethod(0); Usage: TD3DDeclUsage(0); UsageIndex: 0) ); type // 3DS loaded object vertex struct Pz3D3DSObjectVertex = ^Tz3D3DSObjectVertex; Tz3D3DSObjectVertex = packed record Position: TD3DXVector3; TexCoord: TD3DXVector2; end; Pz3D3DSObjectVertexArray = ^Tz3D3DSObjectVertexArray; Tz3D3DSObjectVertexArray = array[0..MaxInt div SizeOf(Tz3D3DSObjectVertex)-1] of Tz3D3DSObjectVertex; T3DSFaceIndices = array[0..3] of Word; Pz3D3DSFile = ^Tz3D3DSFile; // 3DS file chunk object Pz3D3DSFileChunk = ^Tz3D3DSFileChunk; Tz3D3DSFileChunk = object ID: Word; Length: LongWord; Start: LongWord; SubChunks: array of Pz3D3DSFileChunk; Data: Pz3D3DSFile; function NewSubChunk: Integer; procedure Read(var AStream: TStream); destructor Destroy; end; // 3DS file mesh object Tz3D3DSMeshObject = class NumVerts: Cardinal; NumFaces: Cardinal; NumCoords: Cardinal; NumNormals: Cardinal; HasCoords: Boolean; BBMin, BBMax: TD3DXVector3; Faces: array of T3DSFaceIndices; Coords: array of TD3DXVector2; Vertices: array of TD3DXVector3; procedure ComputeBounds; end; // 3DS file object Tz3D3DSFile = object Chunk: Pz3D3DSFileChunk; MeshCount: Cardinal; Meshes: array of Tz3D3DSMeshObject; BBMin, BBMax: TD3DXVector3; function Load(const AFileName: string): ID3DXMesh; procedure Clear; procedure ComputeBounds; procedure CenterVertices; end; Implementation: { 3DS format } procedure SkipChunk(Var F: TStream; Len: longword); begin F.Seek(Len-6, soFromCurrent); end; destructor Tz3D3DSFileChunk.Destroy; var I: integer; begin for I:= 0 to High(SubChunks) do if SubChunks <> nil then begin SubChunks^.Destroy; FreeMem(SubChunks); SubChunks := nil; end; Setlength(SubChunks, 0); end; function Tz3D3DSFileChunk.NewSubchunk: integer; begin Setlength(SubChunks, High(SubChunks)+2); New(subchunks[High(SubChunks)]); SubChunks[High(SubChunks)].Data:= Self.Data; Result:= High(SubChunks); end; procedure Tz3D3DSFileChunk.Read(var AStream: TStream); Var S: string; Ch: Char; I: integer; Version: Cardinal; Temp: Single; W: Word; begin Start := AStream.Position; AStream.ReadBuffer(ID, 2); AStream.ReadBuffer(Length, 4); case ID of // Version information MAX3DS_ID_VERSION: begin AStream.ReadBuffer(Version, 4); if Version > 3 then z3DTrace('Iz3D3DSFileChunk.Read: This file is from a later version of 3DS. It may not load correctly', z3dtkWarning); end; // Mesh object vertices MAX3DS_ID_OBJECT_VERTICES: begin if Data^.MeshCount > 0 then with Data^.Meshes[Data^.MeshCount-1] do begin AStream.ReadBuffer(W, 2); NumVerts:= W; SetLength(Vertices, Numverts); for I:= 0 to NumVerts-1 do begin AStream.ReadBuffer(Vertices, Sizeof(TD3DXVector3)); // Swap Z and Y to make it D3D compatible Temp:= Vertices.y; Vertices.y:= Vertices.z; Vertices.z:= -Temp; end; end; end; // Mesh object texture coordinates MAX3DS_ID_OBJECT_UV: begin if Data^.MeshCount > 0 then with Data^.Meshes[Data^.MeshCount-1] do begin AStream.ReadBuffer(W, 2); NumCoords := W; HasCoords:= True; SetLength(Coords, NumCoords); for I := 0 to NumCoords-1 do AStream.ReadBuffer(Coords, Sizeof(TD3DXVector2)); end; end; // Mesh object face indices MAX3DS_ID_OBJECT_FACES: begin if Data^.MeshCount > 0 then with Data^.Meshes[Data^.MeshCount-1] do begin AStream.ReadBuffer(W, 2); NumFaces := W; SetLength(Faces, NumFaces); For I := 0 to NumFaces-1 do AStream.ReadBuffer(Faces, Sizeof(T3DSFaceIndices)); end; end; // Mesh object information MAX3DS_ID_OBJECTINFO, MAX3DS_ID_HEADER, MAX3DS_ID_OBJECT_MESH: begin repeat SubChunks[NewSubChunk]^.read(AStream); until AStream.Position >= (Start+Length); end; // Mesh object MAX3DS_ID_OBJECT: begin with Data^ do begin Inc(MeshCount); Setlength(Meshes, MeshCount); Meshes[MeshCount-1] := Tz3D3DSMeshObject.Create; end; repeat AStream.ReadBuffer(Ch, 1); // Name of object S := S + Ch; until Ch = #0; repeat SubChunks[NewSubChunk]^.read(AStream); until AStream.Position >= (Start+Length); end; else SkipChunk(AStream, Length); end; end; procedure Tz3D3DSMeshObject.ComputeBounds; var I: integer; Vert: TD3DXVector3; begin BBMin.x := 99999; BBMin.y := 99999; BBMin.z := 99999; BBMax.x := -99999; BBMax.y := -99999; BBMax.z := -99999; for I := 0 to NumVerts-1 do begin Vert.x := Vertices.x; Vert.y := Vertices.y; Vert.z := Vertices.z; if BBMin.x > Vert.x then BBMin.x := Vert.x; if BBMin.y > Vert.y then BBMin.y := Vert.y; if BBMin.z > Vert.z then BBMin.z := Vert.z; if BBMax.x < Vert.x then BBMax.x := Vert.x; if BBMax.y < Vert.y then BBMax.y := Vert.y; if BBMax.z < Vert.z then BBMax.z := Vert.z; end; end; procedure Tz3D3DSFile.CenterVertices; var FCenter: TD3DXVector3; I, J: integer; begin ComputeBounds; FCenter.x:= BBMin.x+FCenter.x/2; FCenter.y:= BBMin.y+FCenter.y/2; FCenter.z:= BBMin.z+FCenter.z/2; for I:= 0 to MeshCount-1 do begin for J:= 0 to Meshes.NumVerts-1 do with Meshes do begin Vertices[J].x:= Vertices[J].x - FCenter.x; Vertices[J].y:= Vertices[J].y - FCenter.y; Vertices[J].z:= Vertices[J].z - FCenter.z; end; end; end; procedure Tz3D3DSFile.ComputeBounds; var I: integer; begin BBMin.x := 99999; BBMin.y := 99999; BBMin.z := 99999; BBMax.x := -99999; BBMax.y := -99999; BBMax.z := -99999; for I := 0 to MeshCount-1 do begin Meshes.ComputeBounds; if BBMin.x > Meshes.BBMin.x then BBmin.x := Meshes.Bbmin.x; if BBMin.y > Meshes.BBMin.y then BBmin.y := Meshes.Bbmin.y; if BBMin.z > Meshes.BBMin.z then BBmin.z := Meshes.Bbmin.z; if BBMax.x < Meshes.BBMax.x then BBmax.x := Meshes.Bbmax.x; if BBMax.y < Meshes.BBMax.y then BBmax.y := Meshes.Bbmax.y; if BBMax.z < Meshes.BBMax.z then BBmax.z := Meshes.Bbmax.z; end; end; procedure Tz3D3DSFile.Clear; var I: integer; begin for I := 0 to High(Meshes) do with Meshes do begin Setlength(Vertices, 0); Setlength(Faces, 0); Setlength(Coords, 0); NumVerts:= 0; NumFaces:= 0; NumCoords:= 0; Meshes.Free; end; Setlength(Meshes, 0); MeshCount := 0; end; function Tz3D3DSFile.Load(const AFileName: string): ID3DXMesh; var FStream: TFilestream; FIB: PWordArray; FVB: Pz3D3DSObjectVertexArray; FFaceCount, FVertexCount: Integer; FCurrentV, FCurrentF, I, J: integer; FVertices: array of TD3DXVector3; FFaces: array of T3DSFaceIndices; FCoords: array of TD3DXVector2; begin if not FileExists(AFileName) then z3DTrace(PWideChar(WideString('Iz3D3DSFile.Load failed: File does not exist. Filename: '+ExtractFileName(AFileName))), z3dtkWarning); // Load the 3DS file try try Clear; FStream:= TFileStream.Create(AFileName, fmOpenRead); New(Chunk); Chunk^.Data := @Self; Chunk^.Read(TStream(FStream)); except on E: Exception do z3DTrace(PWideChar(WideString('Iz3D3DSFile.Load failed: Unknown exception raised while loading the 3DS file. Error message: '+E.Message)), z3dtkWarning); end; if MeshCount = 0 then z3DTrace('Iz3D3DSFile.Load failed: 3DS file does not contain any valid meshes', z3dtkWarning); // Center all meshes CenterVertices; // Convert the meshes to D3D format if MeshCount > 0 then begin FFaceCount:= 0; FVertexCount:= 0; FCurrentV:= 0; FCurrentF:= 0; // Concatenate the vertices for J:= 0 to MeshCount-1 do begin SetLength(FFaces, Length(FFaces)+Meshes[J].NumFaces); for I:= 0 to Meshes[J].NumFaces-1 do begin FFaces[FCurrentF][0]:= Min(MAX3DS_MAXVERTICES-1, Meshes[J].Faces[0]+FVertexCount); FFaces[FCurrentF][1]:= Min(MAX3DS_MAXVERTICES-1, Meshes[J].Faces[1]+FVertexCount); FFaces[FCurrentF][2]:= Min(MAX3DS_MAXVERTICES-1, Meshes[J].Faces[2]+FVertexCount); FFaces[FCurrentF][3]:= Min(MAX3DS_MAXVERTICES-1, Meshes[J].Faces[3]+FVertexCount); Inc(FCurrentF); end; SetLength(FVertices, Length(FVertices)+Meshes[J].NumVerts); SetLength(FCoords, Length(FCoords)+Meshes[J].NumVerts); for I:= 0 to Meshes[J].NumVerts-1 do begin FVertices[FCurrentV].x:= Meshes[J].Vertices.x; FVertices[FCurrentV].y:= Meshes[J].Vertices.y; FVertices[FCurrentV].z:= Meshes[J].Vertices.z; if Meshes[J].HasCoords then begin FCoords[FCurrentV].x:= Meshes[J].Coords.x; FCoords[FCurrentV].y:= Meshes[J].Coords.y; end; Inc(FCurrentV); end; FFaceCount:= FFaceCount+Meshes[J].NumFaces; FVertexCount:= FVertexCount+Meshes[J].NumVerts; end; if FVertexCount > MAX3DS_MAXVERTICES then begin StringToWideChar('Iz3D3DSFile.Load: Imported 3DS file exceeds z3D vertex limit. Trying to truncate the vertex buffer', z3DWideBuffer, 255); z3DTrace(z3DWideBuffer, z3DtkWarning); FVertexCount:= MAX3DS_MAXVERTICES; FFaceCount:= FVertexCount div 3 + 1; end; // Create the D3D mesh if FAILED(D3DXCreateMesh(FFaceCount, FVertexCount, D3DXMESH_MANAGED, @Tz3D3DSObjectVD, z3DCore_GetD3DDevice, Result)) then z3DTrace('Iz3D3DSFile.Load failed: D3DXCreateMesh failed', z3dtkWarning); // Copy the vertices from 3DS to D3D if Result <> nil then begin Result.LockVertexBuffer(0, Pointer(FVB)); Result.LockIndexBuffer(0, Pointer(FIB)); try for I:= 0 to FFaceCount-1 do begin FIB[I*3]:= FFaces[0]; FIB[I*3+1]:= FFaces[1]; FIB[I*3+2]:= FFaces[2]; end; for I := 0 to FVertexCount-1 do begin FVB.Position.x:= FVertices.x; FVB.Position.y:= FVertices.y; FVB.Position.z:= FVertices.z; if Length(FCoords) > 0 then begin FVB.TexCoord.x:= FCoords.x; FVB.TexCoord.y:= FCoords.y; end; end; finally Result.UnlockVertexBuffer; Result.UnlockIndexBuffer; end; end; end; finally FStream.Free; Chunk^.Destroy; Dispose(Chunk); Chunk:= nil; end; end; All you need to do after is to call Tz3D3DSFile.Load(). HTH. Cheers,
  4. jpventoso

    Question about shadow mapping

    ATI also does the depth comparison automatically when you use tex2Dproj() on some hardware. I remember the ATI HD 2400+ doing it.
  5. That looks like the expected precision for a X8R8G8B8 buffer on some cards. The same scene textured should hide those "rings" to the viewer.
  6. Quote:Original post by jcabeleira This question also applies to the shadow generation. Yes, you have to render the scene once per light to generate the shadow map. But when filling the buffer with the shadows, do you store them in separate channels like the CryEngine does, or do you multiply the shadows together? I have the same question. How do you manage to use only one buffer for eight lights? You can't just add or modulate the shadow factor on the same buffer because there is one shadow per light, right?
  7. Quote:Original post by jcabeleiraBut in that case, shading and shadowing aren't truly separated. You still have to write 2 versions of the same shader, one that samples the light mask and another that doesn't. The idea of separating shading and shadowing consists in the fact that you avoid several shader combinations by keeping the shadow computation part on a separate pass. But you'll still need shadow and no-shadow permutations for the lighting part. I think there's no problem with shader permutations in general, but this technique allows to reduce them. In my case, the main achievement of this technique consists to allowing my engine to shade with HQ shadows under sm20. Cheers,
  8. Quote:Original post by maya18222 1. Render whole scene as depth only write to depth buffer 2. Create shadowmaps for each light, (could be a 1 four channel rendertarget for 4 lights, or 2 four channel rendertargets for 8 lights etc etc) 3. Create a third render target, and to this render the shadows in image space. ie go throught all the lights in turn and compare against the depth map and write result to our third render target. 4. Blend the this third rendertarget into our lighting shaders to produce the shadows, where the NDC space for the pixel is converted to UV [0,1] coordinates, so you can then sample the third rendertarget for the shadowing component That's exactly what I'm doing right now, and it works fine (so far) =) Quote:Original post by maya18222 1. when performing stage 3, arent you going to have to do that with a pass for each light? as you have to perform a different world space to light space multiplication so you're comparing values that are in the same space. Or i guess you could just pass in a matrix array of all the light inverse matrices so you can do it all in one pass. Exactly, I pass an array of matrices to the shader (and then transform the world space vertices to light space on the pixel shader, inside the for..loop). Quote:Original post by maya18222 2. Am i right in also thinking stage 2 could be done in one pass, as again you could just pass in a matrix array of all your lights and do something like this for 8 lights. I think that wouldn't work because, in standard shadowmapping, your vertex shader needs to output a single POSITION register. Maybe it could be done using deferred techniques? Another thing that I found interesting about this technique is that you can perform a full-screen blur on all shadowmaps in one pass (of course you'll need to take into account depth difference in order to keep edges sharp): Cheers, Juan Pablo
  9. I recently implemented the same technique in my engine, so my rendering pipeline went from: - render geometry for ambient term and simple lighting - for each shadowmapped light N - - render geometry for light N's shadowmap - - render geometry for light N with shadowmap computation (using additive blending) to: - render geometry for ambient term and simple lighting - for each shadowmapped light N (Max: 4) - - render geometry for light N's shadowmap - for N: 0 to 3 - - if N = 0 then EnableColorWrite(Red) - - if N = 1 then EnableColorWrite(Green) - - if N = 2 then EnableColorWrite(Blue) - - if N = 3 then EnableColorWrite(Alpha) - - render shadowmap computation to shadowmap buffer - render the four shadowmapped lights at once, modulating with shadowmap buffer So I use custom color writes to get a shadowmap buffer with the result for each light on a single color channel. Then I choose the channel to do the modulation based on the current light index (0: red, 1: blue, etc.). I think my rendering method is very similar to yours, except that I render the shadow map buffer first. This allows to ignore shading on pixels that I alredy know are in shadow (this is specially useful if you're pixel bound). This technique is also useful to render the four lights at once (on a single pass) without exceeding the ps20 instruction limit. The shadowmap computation, as you say, can be done using both forward or deferred rendering. HTH =) [Edited by - jpventoso on October 25, 2009 11:55:33 PM]
  10. jpventoso

    SSAO problem in GLSL

    Maybe this could help, You're using your eye position added with the offset for the comparison. I think the common thing is to use your depth for that pixel instead. Your code does: float zd = max(se.z - sampleDepth, 0.0); And I think it should be float zd = max(depth*farPlane - sampleDepth, 0.0); HTH. Regards, Juan Pablo
  11. jpventoso

    limit of TEXCOORD in HLSL

    Quote:Original post by NiGoea I'm using a GeForce 6800.. it was a high-end card. I can't believe it has only four texture units. Anyway, I will try to use the COLORn that you suggested. I have a GeForce 6800 too and it supports at least 6 texcoords.
  12. The lighting and shadowing did it for me. The colors are unreallistic but there's a nice contrast between lit and shadowed areas. That combination is a win.
  13. I figured it out =) I was setting my vertex declaration before on the FrameRender event and it was not set on my GenerateRadiosity procedure... :/ Cheers, Juan Pablo
  14. Hi all, I'm trying to do some offline renderization (for radiosity generation using the GPU) and my simplified code looks like this: procedure GenerateRadiosity; begin // Set up device states PrepareRenderStates; // Prepare our sample surface (16x16) as the render target GPUBuffer.SetRenderTarget; // Iterate through all luxels for I:= 0 to LuxelCount - 1 do begin // Build the view and projection matrix for this luxel BuildView(Luxels); GPUBuffer.Clear; // Draw the objects for this luxel to sample the emissive light for I:= 0 to Shader.Run - 1 do begin Shader.BeginPass(I); DrawObjects; end; // Assign the average as the luxel color Luxel.Color := GetRadiosity(GPUBuffer); end; // Restore previous device states RestoreRenderStates; end; It works just fine if I call GenerateRadiosity from inside a FrameRender event (with the usual BeginScene...EndScene...Present chain): procedure Engine.FrameRender; begin Renderer.BeginScene; ...scene stuff... if GenerateRadiosityNow then GenerateRadiosity; ...scene stuff... Renderer.EndScene; Renderer.Present; end; But then, I wanted to isolate the radiosity generation from the FrameRender event (so I could call it anytime in my loop). So, I added a BeginScene...EndScene pair inside the GenerateRadiosity procedure: procedure GenerateRadiosity; begin // Begin renderization Device.BeginScene; ...previous code... // End renderization Device.EndScene; end; But it stopped working. The target is cleared just fine, but nothing is drawn into the texture. All renderization methods returns SUCCEDED results, and the debug runtime doesn't show any warnings. Is it correct to call a BeginScene...EndScene set without calling Present after? Is this the regular way to use the GPU for an offline renderization? Thanks in advance! Juan Pablo. [Edited by - jpventoso on June 17, 2009 5:29:16 PM]
  15. AFAIK, Direct3D is the right way to go on 2D right now. It has a lot of advantages like leet bix said, and DirectDraw has been deprecated lately. Also, you can load all textures when the map/level/scene loads, put them in the MANAGED pool, and let Direct3D decide when to move them into video or not. That way, your video card wont run out of memory because Direct3D sends only the displayed textures to the vRAM. HTH.
  • Advertisement

Important Information

By using, you agree to our community Guidelines, Terms of Use, and Privacy Policy. is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!