Page 1 of 3 123 LastLast
Results 1 to 10 of 24

Thread: Volumetric Clouds

  1. #1

    Volumetric Clouds

    Hi all,

    I found a C++ OpenGL example of Volumetric Clouds a while back, and found it on my HDD while cleaning up.. so i am trying to make a GLScene port of it... now my C++ skills are urm some what limited, but i have managed to convert it (at least to the best of my knowledge).

    It seems to compile ok without errors or warnings, but i can't seem to get it to work very well.

    There are 2 main routines that need to be called, update and render (of course), if i just have update then the program runs, however if i have update and render then the program crashes on every 8 or 12 loop cycle with an 'Access Violation', now i suspect that it has something to do with the call to glDrawArrays(GL_QUADS, 0, Length(Cloud.vBuffer));, this routine is in both the RenderCloud3D procedure (called when rendering) and MakeCloudImpostor procedure (called when upating).

    Its either because my conversion is rubbish, or i need to put some form of delay between updating and rendering, or some other means.
    Any suggestions?

    Heres the code to browse: Here

    Many thanks
    Nic

    p.s. sorry the code is some what a mess....

    EDIT:
    I decided to double check the cloud data being read, would having the single values out of range cause access violations?

    if so, is there a problem between the method i load the data file compared to the method from c++?
    M109uk
    <br />--------------------------------------------------------
    <br />www.pulse-soft.oneuk.com

  2. #2

    Volumetric Clouds

    I wonder if problem is here:
    [pascal]glVertexPointer(3, GL_FLOAT, 0, @Cloud.vBuffer);
    glColorPointer(4, GL_FLOAT, 0, @Cloud.cBuffer);
    glTexCoordPointer(2, GL_FLOAT, 0, @Cloud.tBuffer);[/pascal]

    I don't have GLScene installed to test but try using

    [pascal]glVertexPointer(3, GL_FLOAT, 0, @Cloud.vBuffer[0]);
    glColorPointer(4, GL_FLOAT, 0, @Cloud.cBuffer[0]);
    glTexCoordPointer(2, GL_FLOAT, 0, @Cloud.tBuffer[0]);[/pascal]

    Setlength made dynamic arrays don't work same way as normal or allocated ones if i remember, instead it's like a pointer to memory space that contains the cells in an array.

  3. #3

    Volumetric Clouds

    Wow, sharp eye... that seemed to have solved the access violation errors

    Now the only problem is that the speed is, urm well none existant..

    Many thanks
    M109uk
    <br />--------------------------------------------------------
    <br />www.pulse-soft.oneuk.com

  4. #4

    Volumetric Clouds

    Hi,

    Im still trying to find out why my version is a lot slower than the C++ version, although i have a few ideas of my own to speed it up. but for now i wish to confirm that my C++ conversion is urm correct.. the main parts i am unsure about are the following:

    from:
    Code:
    inline float __fastcall carmack_func&#40;float x&#41;
    &#123;
    	int carmack;
    	float isx, halfx;	//Inverse Squareroot of x
    
    	halfx = 0.5f*x;
    	carmack = *&#40;int*&#41;&x; 
    	carmack = 0x5f3759df - &#40;carmack>>1&#41;; 
    	isx = *&#40;float*&#41;&carmack; 
    
    	isx = isx*&#40;1.5f-halfx*isx*isx&#41;;  //Newton-Rhapson step, add more for accuracy
    
    	return isx;
    &#125;
    to:
    [pascal]
    function carmack_func(x: Single): Single;
    var
    carmack: Integer;
    isx,halfx: Single;
    begin
    halfx := 0.5*x;
    carmack := Round(x);
    If carmack > 1 Then
    carmack := $5f3759df-(carmack) Else
    carmack := $5f3759df-(1);
    isx := carmack;
    isx := isx*(1.5-halfx*isx*isx);
    Result := isx;
    end;
    [/pascal]

    the above im sure is wrong, because i really did'nt have a clue about parts of the code and could'nt find any resources.

    from:
    Code:
    		*&#40;vp++&#41; = Puff->Position + Corner1 * Puff->Size;
    		*&#40;tp++&#41; = v1;
    		*&#40;cp++&#41; = ParticleColor;
    to:
    [pascal]
    Cloud.vBuffer[j] := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner1[0]*Cloud.Puffs[i].Size,
    Cloud.Puffs[i].Position[1]+Corner1[1]*Cloud.Puffs[i].Size,
    Cloud.Puffs[i].Position[2]+Corner1[2]*Cloud.Puffs[i].Size);
    Cloud.tBuffer[j] := v1;
    Cloud.cBuffer[j] := ParticleColor;
    Inc(j);
    [/pascal]

    now im fairly confident in assuming this is going through the array's setting the values?!

    and another question, is having the records/classes as a pointer quicker?

    e.g.

    vBuffer: Array Of TVector3f;
    ..
    for j := 0 to 2500 do vBuffer[i] := Vector3fMake(0,0,0);

    Many thanks
    Nic
    M109uk
    <br />--------------------------------------------------------
    <br />www.pulse-soft.oneuk.com

  5. #5

    Volumetric Clouds

    I know it might not work, or yield similar results (I'm not good with C), but this should do what you're after. I tried reducing the legwork that was going on as much as possible to speed things up though. Try this:
    Code:
    function carmack_func&#40;const x&#58; double&#41;&#58; double; inline;
    var halfx&#58; double;
        carmack&#58; integer;
    begin
      halfx &#58;= x * 0.5; // Floating point multiplication is usually faster.
      carmack &#58;= $5f3759df - &#40;int&#40;x&#41; shr 1&#41;;
      result &#58;= carmack * &#40;1.5 - halfx * carmack * carmack&#41;;
    end;
    To speed that up further, try changing it to a procedure and pass the floating point result as an OUT parameter. That could speed things a little.

    I don't know about the second part. It's been years since I touched OpenGL by hand, and even then I wasn't particularly good at it. However, you might be faster at it if you pass things as a record ... I just don't know. You could try using a pointer for increased speed, but I don't know if there would be a gain there. Try this to see:
    Code:
    procedure pointerWalk;
    var 
      vBuffer&#58; PVector3f;
      count&#58; integer;
    begin
      count &#58;= 2500;
      // Assign the memory block to the pointer, I don't remember the Delphi
      // code off-hand.  But the size is 'SizeOf&#40;TVector3f&#41;*2500' if you need
      // to know how.  &#58;P
      repeat
        vBuffer^ &#58;= Vector3fMake&#40;0,0,0&#41;;
        Inc&#40;vBuffer&#41;;
        Dec&#40;Count&#41;;
      until count = 0;
    end;
    I honestly don't know that it'd make much of a difference, if any.

    Oh, and all this was written in ConText/Firefox, so no promises that it actually functions as-is. You might need to tweak it a little.

    EDIT:

    On second thought, if you're only making a blank array of vectors it'd be faster to do:
    Code:
    FillChar&#40;vBuffer, #0, SizeOf&#40;vBuffer&#41;&#41;;
    That's as utterly fast as you can do it without assembler.

  6. #6

    Volumetric Clouds

    Great thanks for the quick reply

    I have inserted your carmack_func, there where 2 problems, delphi didn't like the inline; nor the int(X), but removing the inline; and changing int(x) to Round(x) seems to compile

    I shall try using the pointers now, i noticed that pointers where being used in the C++ version, but since im not too good with pointers i tried it using records instead.

    I shall post back with the results

    Thanks again
    Nic
    M109uk
    <br />--------------------------------------------------------
    <br />www.pulse-soft.oneuk.com

  7. #7

    Volumetric Clouds

    Hi again,

    I have changed the code to use pointers instead, however i am getting an access violation error when i add data to the pointer (around the 20th item to be added)

    am i doing something wrong...

    heres the code im using:
    [pascal]
    //---- load cloud data
    GetMem(Cloud.vBuffer, (SizeOf(TVector3f)*(Length(Cloud.Puffs)*4)));
    GetMem(Cloud.tBuffer, (SizeOf(TVector3f)*(Length(Cloud.Puffs)*4)));
    GetMem(Cloud.cBuffer, (SizeOf(TVector3f)*(Length(Cloud.Puffs)*4)));

    //---- add data to pointers
    procedure AddToMem(Cloud: TVolumetricCloud; v2: TVector2f; v3: TVector3f; v4a,v4b: TVector4f);
    begin
    Cloud.vBuffer^ := v3;
    Inc(Cloud.vBuffer); <-------------- ERROR HERE
    Cloud.cBuffer^ := v4a;
    Inc(Cloud.cBuffer);
    Cloud.IcBuffer^ := v4b;
    Inc(Cloud.IcBuffer);
    Cloud.tBuffer^ := v2;
    Inc(Cloud.tBuffer);
    end;

    //

    For i := 0 To High(Cloud.Puffs) Do
    Begin

    iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner1[0]*Cloud.Puffs[i].Size,
    Cloud.Puffs[i].Position[1]+Corner1[1]*Cloud.Puffs[i].Size,
    Cloud.Puffs[i].Position[2]+Corner1[2]*Cloud.Puffs[i].Size);
    AddToMem(Cloud, v1, iv3, pColor, pColor2);
    iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner2[0]*Cloud.Puffs[i].Size,
    Cloud.Puffs[i].Position[1]+Corner2[1]*Cloud.Puffs[i].Size,
    Cloud.Puffs[i].Position[2]+Corner2[2]*Cloud.Puffs[i].Size);
    AddToMem(Cloud, v2, iv3, pColor, pColor2);
    iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner3[0]*Cloud.Puffs[i].Size,
    Cloud.Puffs[i].Position[1]+Corner3[1]*Cloud.Puffs[i].Size,
    Cloud.Puffs[i].Position[2]+Corner3[2]*Cloud.Puffs[i].Size);
    AddToMem(Cloud, v3, iv3, pColor, pColor2);
    iv3 := Vector3fMake(Cloud.Puffs[i].Position[0]+Corner4[0]*Cloud.Puffs[i].Size,
    Cloud.Puffs[i].Position[1]+Corner4[1]*Cloud.Puffs[i].Size,
    Cloud.Puffs[i].Position[2]+Corner4[2]*Cloud.Puffs[i].Size);
    AddToMem(Cloud, v4, iv3, pColor, pColor2);
    End;
    [/pascal]

    im sure i've missed something really dumb..

    Thanks
    Nic
    M109uk
    <br />--------------------------------------------------------
    <br />www.pulse-soft.oneuk.com

  8. #8

    Volumetric Clouds

    What are the types of the Cloud properties: vBuffer, tBuffer, cBuffer? I'm not a pointer expert, but I think I made a mistake and gave the wrong type; etc. A potential problem is that you're manipulating what should be the list "head" rather than the current item on the tail. Hard to say without knowing the actual types in this case.

  9. #9

    Volumetric Clouds

    Ah sorry, i forgot to post that bit ops:

    type
    PVector2f = ^TVector2f;
    PVector3f = ^TVector3f;
    PVector4f = ^TVector4f;

    TVolumetricCloud = Class
    //
    vBuffer: PVector3f;
    tBuffer: PVector2f;
    cBuffer: PVector4f;
    IcBuffer: PVector4f;
    end;

    Thanks
    M109uk
    <br />--------------------------------------------------------
    <br />www.pulse-soft.oneuk.com

  10. #10

    Volumetric Clouds

    Mind you, Int() is not the equivalent of round(). I think you'd be better off with trunc().

    see

    [pascal]ShowMessage('Round(12.75) = '+IntToStr(Round(12.75)));
    ShowMessage('Trunc(12.75) = '+IntToStr(Trunc(12.75)));
    ShowMessage(' Int(12.75) = '+FloatToStr(Int(12.75)));[/pascal]
    or this site.

Page 1 of 3 123 LastLast

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
  •