Author Topic: [ADDED] More VBQuad control  (Read 12551 times)

0 Members and 1 Guest are viewing this topic.

James Brown

  • Thug
  • *
  • Posts: 10
[ADDED] More VBQuad control
« on: March 10, 2008, 11:06:05 PM »
VBQuads are really useful for lots of the stuff we do in Hyperion, but with a few additions they'd be even better...

It would be useful to be able to remove quads from a vbquad. We can HYP_Mesh.VBQuad_AddQuad(), but once it's added, it's there for good. HYP_Mesh.VBQuad_Clear() would add a lot of flexibility.

There are functions to change the vertex colour and position of quads, but once they're added it's no longer possible to change the texture coordinates. HYP_Mesh.VBQuad_SetQuadVertexUVCoords() would be handy.

It would also be nice if we could set 4d texture coordinates instead of just 2d.

Cheers!
James.
« Last Edit: April 29, 2008, 01:05:30 PM by JeGX »

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2385
    • oZone3D.Net
Re: More VBQuad control
« Reply #1 on: March 27, 2008, 09:48:18 PM »
Hi James,

yes you're right, some functions are missing, it's a fact!
Ok for HYP_Mesh.VBQuad_Clear() and HYP_Mesh.VBQuad_SetQuadVertexUVCoords() and the one for the color.

status: ACCEPTED

James Brown

  • Thug
  • *
  • Posts: 10
Re: [ACCEPTED] More VBQuad control
« Reply #2 on: March 31, 2008, 03:51:33 AM »
Excellent, thanks!

I thought you might like to see an experiment I did, to see how many vbquads I could play with. It uses a pair of textures to store the positions and velocities of each quad, updating them using a shader, so everything stays on the GPU where it can be nice and fast.

This runs with 90000 quads at 175 fps on my GeForce 8800. (I haven't tried it on any other card - I can't guarantee it'll work at all).

Unfortunately Demoniak crashes when I try to use more vbquads - if you want to reproduce this, increase the size of tex_star0 and tex_star1 to 316x316, and increase vbq_grains to 99856. It would be really cool if you could find out why this is happening. I'd like to try it with 1000000 quads!

Interestingly, it actually runs slower with a vertex pool than with vbquads. (I'm also stretching the quads to create motion blur, which you can't do with a vertex pool.)

Anyway, it's quite pretty in action:

Quote

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>

<hyperion version="1.0">
   
<scene    name="Swarm"
      clear_color_buffer="TRUE"
      display_fps="TRUE"
      show_ref_grid="FALSE"
      display_hyperion_logo="FALSE"
      vsync="FALSE" >
   
   <window_size width="1024" height="768" />
   <background_color r="0" g="0" b="0" />
   <wait_screen image="startup.jpg" />
</scene>

<camera name="cam_default" fov="1.0" navigation_mode="FIXED" near_plane="1" far_plane="1000" >
   <position x="0" y="0" z="5" />
   <lookat x="0" y="0" z="0" w="1" />
</camera>

<texture name="tex_star0" type="TEXTURE_RECTANGLE_2D" use_fbo_for_rtt="TRUE" pixel_format="RGBA_32F" filtering_mode="NONE" addressing_mode="MIRROR" >
   <size width="300" height="300" />
</texture>
<texture name="tex_star1" type="TEXTURE_RECTANGLE_2D" use_fbo_for_rtt="TRUE" pixel_format="RGBA_32F" filtering_mode="NONE" addressing_mode="MIRROR" >
   <size width="300" height="300" />
</texture>
<mesh name="vbq_grains0" shape_type="VB_QUAD" render="FALSE" polygon_mode="SOLID"
   group="content" display_bounding_sphere="FALSE"
   lighting="FALSE" texturing="TRUE" back_face_culling="FALSE" use_vbo="TRUE" >
   <vb_quad num_vb_quads="90000" />
   <attach_material name="mat_grains" />
   <blending_params active="TRUE" src_factor="BLENDING_FACTOR_SRC_ALPHA" dst_factor="BLENDING_FACTOR_ONE" />
</mesh>

<material name="mat_star">
   <add_texture
      texture_unit="0"
   />
</material>

<hud name="hud_star"
   group="simulation"
   material_name="mat_star"
   texturing="TRUE"
   render="FALSE" >
</hud>

<material name="mat_grains" opacity="0.999" shader_program_name="shd_grains" >
   <add_texture
      texture_unit="0"
   />
   <add_texture
      texture_unit="1"
   />
</material>

<primitive name="prm_grain" shape_type="QUAD" render="FALSE" texturing="FALSE" lighting="FALSE" display_tripod="FALSE" >
   <quad width="1.0" height="1.0" billboarding="FALSE" />
</primitive>
   
   
<shader_program name="shd_stars" >
   <constant_1i name="Star" value="0" />
   <constant_2f name="Attractor" />
   <raw_data><![CDATA[   
[Vertex_Shader]

void main(void)
{
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
   gl_TexCoord[0] = gl_MultiTexCoord0;
   gl_FrontColor = gl_Color;
}


[Pixel_Shader]
#extension GL_ARB_texture_rectangle : enable

uniform sampler2DRect   Star;
uniform vec2         Attractor;

vec2 Force(vec4 star, vec2 attractor, vec2 uid)
{
   vec2 offset = star.xy-attractor;

   float dist = length(offset)+1.;
   attractor += offset.yx/dist * vec2(1.,-1.)*max(0.,dist-8.)*(0.5+uid.y);
   offset = star.xy-attractor;
   float oof = 1.+4.*uid.x;

   return offset * -oof/dot(offset,offset);
}

void main(void)
{

   vec4 star = texture2DRect(Star, gl_TexCoord[0].st);
   vec2 uid = (gl_TexCoord[0].st-(gl_TexCoord[0].ts/256.))/256.;
   
   vec2 acc = Force(star,Attractor,uid);

   star.zw += acc;
   star.xy += star.zw;
   star.zw *= 0.978+0.02*uid.y;
   float maxv = 2.+2.*(1.-uid.y);
   if (dot(star.zw,star.zw)>maxv*maxv)
   {
      star.zw = normalize(star.zw)*maxv;
   }
   
   if (any(lessThan(star.xy,vec2(-768.,-576.))) || any(greaterThan(star.xy,vec2(768.,576.))))
   {
      star.xy = (fract((gl_TexCoord[0].st/128.)+(star.wz*31.7)+(star.yx*71.3))-0.5)*vec2(1024.,768.);
      star.zw = 0.;
   }   

   gl_FragColor = star;
}
      ]]></raw_data>
</shader_program>

<shader_program name="shd_grains" >
   <constant_1i name="Star" value="0" />
   <constant_1i name="StarP" value="1" />
   <raw_data><![CDATA[   
[Vertex_Shader]
#extension GL_ARB_texture_rectangle : enable

uniform sampler2DRect   Star;
uniform sampler2DRect   StarP;

void main(void)
{
   gl_FrontColor = gl_Color;
   vec4 position = gl_Vertex;

   vec4 sim = texture2DRect(Star, gl_MultiTexCoord1.xy);

   //motion blur - leading verts come from current sim, trailing come from previous   
   vec2 simp = texture2DRect(StarP, gl_MultiTexCoord1.xy).xy;
   vec2 mot = sim.xy-simp;
   float len = length(mot);
   gl_FrontColor.a /= 1.+len*0.5;
   
   if (dot(mot, position.xy) < 0.)
   {
      //trailing vert
      const float exaggerate = 2.;
      sim.xy -= mot*exaggerate;
   }
   
   //apply sim info to vert pos
   float radius = 1.;
   position.xy = position.xy*radius + sim.xy;

   gl_Position = gl_ModelViewProjectionMatrix * position;
   gl_TexCoord[1] = gl_Vertex;
}


[Pixel_Shader]
#extension GL_ARB_texture_rectangle : enable

uniform sampler2DRect   Star;
uniform sampler2DRect   StarP;

void main(void)
{
   vec4 colour = gl_Color;
   colour.a *= (1.-dot(gl_TexCoord[1].xy,gl_TexCoord[1].xy));

   gl_FragColor = colour;
}
      ]]></raw_data>
</shader_program>

<script name="Initialise" run_mode="EXECUTE_ONCE" >
   <raw_data><![CDATA[
   
function SwarmInit()
   HYP_Input.SetDefaultInputManagementState(0);
   
   swarm_sim = {HYP_Texture.GetIdFromName("tex_star0"),HYP_Texture.GetIdFromName("tex_star1")};

   swarm_page = 1;
   swarm_nextframe = 0;
   swarm_timer = 0;
   swarm_grains = HYP_Mesh.GetNumFaces("vbq_grains0")/2;

   SwarmInitUVs();

   swarm_fbo = HYP_Scene.FboGetDefault();
   HYP_Scene.FboBind(swarm_fbo);
   HYP_Scene.FboAttachTexture(swarm_sim[1], 0);
   HYP_Scene.FboAttachTexture(swarm_sim[2], 1);
   HYP_Scene.FboBind(0);

   SwarmInitQuads();

   HYP_Material.AttachTexture("mat_star", swarm_sim[1], 0);
   HYP_Material.SetShaderProgram("mat_star", "shd_stars");
   
   
   local w,h = HYP_Texture.GetDimensions(swarm_sim[1]);
   local grains = math.min(swarm_grains, w*h)-1;
   for i=0,grains do
      HYP_Texture.SetValueTex2DFloatRgba(swarm_sim[1],i, (math.random()-0.5)*1024,(math.random()-0.5)*768,(math.random()-0.5)*2,(math.random()-0.5)*2);
   end
end

function SwarmInitUVs()
   local w,h = HYP_Texture.GetDimensions(swarm_sim[1]);
   HYP_Hud.SetVertexTexCoord("hud_star", 0, 0, 0, 0);
   HYP_Hud.SetVertexTexCoord("hud_star", 1, w, 0, 0);
   HYP_Hud.SetVertexTexCoord("hud_star", 2, 0, h, 0);
   HYP_Hud.SetVertexTexCoord("hud_star", 3, w, h, 0);
   HYP_Hud.SetSize("hud_star", w,h);
   HYP_Object.SetPosition("hud_star", -(1024-w)/2, -(768-h)/2);
   HYP_Object.Update("hud_star");
end
   
function SwarmInitQuads()
   HYP_Scene.RemoveObject("prm_grain");

   local vbqgrains0 = HYP_Object.GetIdFromName("vbq_grains0");
   local w,h = HYP_Texture.GetDimensions(swarm_sim[1]);

   local c = 0;
   for y=0,h-1 do
      for x=0,w-1 do
         if c<swarm_grains then
            SwarmAddQuad(vbqgrains0, x,y);
         end
      end
   end

   local ps = (100/768)*math.tan(HYP_Camera.GetFOV("cam_default")*math.pi/180);

   HYP_Object.SetRenderState(vbqgrains0,1);
   HYP_Object.SetPosition(vbqgrains0, 0,0,-100);
   HYP_Object.SetScale(vbqgrains0, ps,ps,ps);
end

function SwarmAddQuad(vbq, x, y)
   HYP_Primitive.SetQuadVertexPosition( "prm_grain", 0, -1,-1,0);
   HYP_Primitive.SetQuadVertexPosition( "prm_grain", 1,  1,-1,0);
   HYP_Primitive.SetQuadVertexPosition( "prm_grain", 2, -1, 1,0);
   HYP_Primitive.SetQuadVertexPosition( "prm_grain", 3,  1, 1,0);

   local r = 0.25+0.50*math.random();
   local g = 0.50+0.50*math.random();
   local b = 0.75+0.25*math.random();
   local a = 0.85;

   HYP_Primitive.SetQuadVertexColor(    "prm_grain", 0, r,g,b,a);
   HYP_Primitive.SetQuadVertexColor(    "prm_grain", 1, r,g,b,a);
   HYP_Primitive.SetQuadVertexColor(    "prm_grain", 2, r,g,b,a);
   HYP_Primitive.SetQuadVertexColor(    "prm_grain", 3, r,g,b,a);
   
   HYP_Primitive.SetQuadVertexTexCoords("prm_grain", 0, 0, 0,0);
   HYP_Primitive.SetQuadVertexTexCoords("prm_grain", 1, 0, 1,0);
   HYP_Primitive.SetQuadVertexTexCoords("prm_grain", 2, 0, 0,1);
   HYP_Primitive.SetQuadVertexTexCoords("prm_grain", 3, 0, 1,1);

   HYP_Primitive.SetQuadVertexTexCoords("prm_grain", 0, 1, x,y);
   HYP_Primitive.SetQuadVertexTexCoords("prm_grain", 1, 1, x,y);
   HYP_Primitive.SetQuadVertexTexCoords("prm_grain", 2, 1, x,y);
   HYP_Primitive.SetQuadVertexTexCoords("prm_grain", 3, 1, x,y);

   HYP_Mesh.VBQuad_AddQuad(vbq, "prm_grain");
end

function SwarmUpdate()
   swarm_timer = swarm_timer + HYP_GetTimeStep();
   if swarm_timer >= swarm_nextframe then
      swarm_nextframe = math.max(swarm_nextframe+(1/60),swarm_timer);

      HYP_Scene.FboBind(swarm_fbo);
      
      local x,y = HYP_Input.GetMousePos();
      HYP_GPUShader.SetConstant_2f("shd_stars", "Attractor", x-512,384-y);

      HYP_Material.AttachTexture("mat_star", swarm_sim[(2-swarm_page)], 0);
      HYP_Scene.FboSetRenderDestination(swarm_page);
      HYP_Object.Render("hud_star");
      
      HYP_Material.AttachTexture("mat_star", swarm_sim[1+swarm_page], 0);
      HYP_Material.AttachTexture("mat_grains", swarm_sim[1+swarm_page], 0);
      HYP_Material.AttachTexture("mat_grains", swarm_sim[2-swarm_page], 1);
      swarm_page = 1-swarm_page;

      HYP_Scene.FboBind(0);
   end
end

SwarmInit();

      ]]></raw_data>
</script>



<script name="Update" run_mode="EXECUTE_EACH_FRAME" >
   <raw_data><![CDATA[
      SwarmUpdate();
   ]]></raw_data>
</script>

</hyperion>



JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2385
    • oZone3D.Net
Re: [ACCEPTED] More VBQuad control
« Reply #3 on: March 31, 2008, 07:18:57 PM »
Awesome! Nice effect James!
In my case, Demoniak crashes with 85,000 vbquads. I will look at this BUG for the next release (Dem 1.23.0).

For lazy but curious people, here are some screenshots. The demo follows the mouse position. I set 84,000 vbquads and the demo runs  at 240 FPS.





JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2385
    • oZone3D.Net
Re: [ACCEPTED] More VBQuad control
« Reply #4 on: April 28, 2008, 09:52:42 AM »
status: ACTIVE.

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2385
    • oZone3D.Net
Re: [ACTIVE] More VBQuad control
« Reply #5 on: April 29, 2008, 01:05:19 PM »
status: ADDED

JeGX

  • Global Moderator
  • Capo Crimine
  • *****
  • Posts: 2385
    • oZone3D.Net
Re: [ADDED] More VBQuad control
« Reply #6 on: April 29, 2008, 04:38:27 PM »
I looked at the crash and it seems to come from memory allocation. VBQuad is a nice feature of Demoniak3D but it has been coded in a dirty manner  :oops: and 90,000 quads require about 800Mb of memory  :coop: Depending of what you have already in system memory (I mean other apps) the Windows memory allocator fails on Demoniak3D voracious request. I added an error management in Dem 1.23.0 and if Demoniak detects a memory failure (XML script or LUA VBQuad_Create() function) you can see it. The only solution to handle a huge number of quads is to rewrite properly the VBQuad! Will do for Dem 2.x.x  :twisted: