def __init__(self, render_size):
        global glLibInternal_ray_shader, glLibInternal_draw_volume_shader
        self.render_size = list(render_size)
        self.ray_fbo = glLibFBO(self.render_size)
        self.ray_fbo.add_render_target(1, GLLIB_RGBA)
        self.ray_fbo.add_render_target(2, GLLIB_RGBA)
        try:
            glLibInternal_ray_shader
            glLibInternal_draw_volume_shader
        except:
            glLibInternal_ray_shader = glLibShader()
            glLibInternal_ray_shader.use_prebuilt(GLLIB_INTERNAL_VOLUME_RAY)

            glLibInternal_draw_volume_shader = glLibShader()
            glLibInternal_draw_volume_shader.use_prebuilt(
                GLLIB_INTERNAL_VOLUME_DRAW)
        self.box = glLibRectangularSolid([0.5, 0.5, 0.5],
                                         texture=GLLIB_TEXTURE_3D,
                                         normals=GLLIB_FACE_NORMALS)
Beispiel #2
0
    def __init__(self, size, pos_data, rip_texture=None, stretched=1.0):
        #TODO: Make kernel size work!
        #Angle limiting forces

        #Size
        if type(size) in [type([]), type(())]:
            self.size = list(size)
        else:
            self.size = [size, size]

        #Misc.
        self.view_2d = glLibView2D((0, 0, self.size[0], self.size[1]))

        #Physics
        self.forces = [0.0, 0.0, 0.0]

        #Cloth Parameters
        self.dampening = 0.98
        self.tensor = 1.0
        self.angle_tensor = 0.0  #1.0
        self.max_jitter_length = 1.0
        self.gravity = [0.0, 0.0, 0.0]
        self.kernel_size = 1
        self.steps = 1
        self.normal_flip = False
        self.loop = [False, False]
        self.time_step = 1.0

        #Collision Objects
        self.num_obstacles = 0
        self.collidable = {}
        self.is_garment = False

        #Geometry
        self.particles = glLibGrid2D(self.size)
        self.particles_mesh = glLibGrid2DMesh(self.size)

        #Textures
        self.pos_restrained_tex = glLibTexture2D(
            pos_data, (0, 0, self.size[0], self.size[1]),
            GL_RGBA,
            precision=32)
        ##        self.
        self.original_pos_restrained_tex = self.pos_restrained_tex
        self.velocity_tex = glLibTexture2D(None,
                                           (0, 0, self.size[0], self.size[1]),
                                           GL_RGB,
                                           precision=32)
        self.vec_tex = None
        self.normal_tex = None
        self.dist_edges_tex = None
        self.dist_corners_tex = None
        self.diffuse_texture = None
        self.obstacles_tex = None
        self.obstacles_aux_param_tex = None
        self.texture_repeat = [1.0, 1.0]

        #FBOs
        self.update_framebuffer = glLibFBO(self.size)
        self.update_framebuffer.add_render_target(1,
                                                  precision=32,
                                                  type=GLLIB_RGBA)
        self.update_framebuffer.add_render_target(2, precision=32)
        self.update_framebuffer.add_render_target(3,
                                                  precision=8)  #for debugging
        self.collision_framebuffer = glLibFBO(self.size)
        self.collision_framebuffer.add_render_target(1,
                                                     precision=32,
                                                     type=GLLIB_RGBA)
        self.collision_framebuffer.add_render_target(2, precision=32)
        self.collision_framebuffer.add_render_target(3, precision=8)
        self.normal_framebuffer = glLibFBO(self.size)
        self.normal_framebuffer.add_render_target(1)
        self.dist_angle_framebuffer = glLibFBO(self.size)
        self.dist_angle_framebuffer.add_render_target(1,
                                                      precision=32,
                                                      type=GLLIB_RGBA)
        self.dist_angle_framebuffer.add_render_target(2,
                                                      precision=32,
                                                      type=GLLIB_RGBA)
        self.set_loop(*self.loop)

        #Shaders
        ##        print "Compiling Update Shader"
        self.update_shader = glLibShader()
        self.update_shader.use_prebuilt(GLLIB_CLOTH_UPDATE)
        ##        print "Compiling Collision Shader"
        self.collision_shader = glLibShader()
        self.collision_shader.use_prebuilt(GLLIB_CLOTH_COLLIDE)
        ##        print "Compiling Normal Shader"
        self.normal_shader = glLibShader()
        self.normal_shader.use_prebuilt(GLLIB_CLOTH_NORMAL)
        ##        print "Compiling Draw Shader"
        self.draw_shader = glLibShader()
        self.draw_shader.use_prebuilt(GLLIB_CLOTH_DRAW)
        ##        print "Compiling Distance Shader"
        self.dist_shader = glLibShader()
        self.dist_shader.use_prebuilt(GLLIB_CLOTH_DISTANCE)
        ##        self.update_shader.save_vertex()

        #Get Target Distances
        self.glLibInternal_push()
        self.dist_angle_framebuffer.enable([1, 2])
        self.glLibInternal_use_dist_shader()
        self.dist_shader.pass_float("stretched", stretched)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        self.view_2d.set_view()
        self.particles.draw()
        glLibUseShader(None)
        self.dist_angle_framebuffer.disable()
        self.glLibInternal_pop()
        self.dist_edges_tex = self.dist_angle_framebuffer.get_texture(1)
        self.dist_corners_tex = self.dist_angle_framebuffer.get_texture(2)

        #Initialize Position
        self.glLibInternal_initialize_position()
Beispiel #3
0
    def __init__(self, size, pos_data, rip_texture=None, stretched=1.0):
        # TODO: Make kernel size work!
        # Angle limiting forces

        # Size
        if type(size) in [type([]), type(())]:
            self.size = list(size)
        else:
            self.size = [size, size]

        # Misc.
        self.view_2d = glLibView2D((0, 0, self.size[0], self.size[1]))

        # Physics
        self.forces = [0.0, 0.0, 0.0]

        # Cloth Parameters
        self.scale = 1.0
        self.trans = [0.0, 0.0, 0.0]
        self.dampening = 0.98
        self.tensor = 1.0
        self.angle_tensor = 0.0  # 1.0
        self.max_jitter_length = 1.0
        self.gravity = [0.0, 0.0, 0.0]
        self.kernel_size = 1
        self.steps = 1
        self.normal_flip = False
        self.loop = [False, False]
        self.time_step = 1.0

        # Collision Objects
        self.num_obstacles = 0
        self.collidable = {}
        self.is_garment = False

        # Geometry
        self.particles = glLibGrid2D(self.size)
        self.particles_mesh = glLibGrid2DMesh(self.size)

        # Textures
        self.pos_restrained_tex = glLibTexture2D(pos_data, (0, 0, self.size[0], self.size[1]), GL_RGBA, precision=32)
        ##        self.
        self.original_pos_restrained_tex = self.pos_restrained_tex
        self.velocity_tex = glLibTexture2D(None, (0, 0, self.size[0], self.size[1]), GL_RGB, precision=32)
        self.vec_tex = None
        self.normal_tex = None
        self.dist_edges_tex = None
        self.dist_corners_tex = None
        self.diffuse_texture = None
        self.obstacles_tex = None
        self.obstacles_aux_param_tex = None
        self.texture_repeat = [1.0, 1.0]

        # FBOs
        self.update_framebuffer = glLibFBO(self.size)
        self.update_framebuffer.add_render_target(1, precision=32, type=GLLIB_RGBA)
        self.update_framebuffer.add_render_target(2, precision=32)
        self.update_framebuffer.add_render_target(3, precision=8)
        self.collision_framebuffer = glLibFBO(self.size)
        self.collision_framebuffer.add_render_target(1, precision=32, type=GLLIB_RGBA)
        self.collision_framebuffer.add_render_target(2, precision=32)
        self.collision_framebuffer.add_render_target(3, precision=8)
        self.normal_framebuffer = glLibFBO(self.size)
        self.normal_framebuffer.add_render_target(1)
        self.dist_angle_framebuffer = glLibFBO(self.size)
        self.dist_angle_framebuffer.add_render_target(1, precision=32, type=GLLIB_RGBA)
        self.dist_angle_framebuffer.add_render_target(2, precision=32, type=GLLIB_RGBA)
        self.set_loop(*self.loop)

        # Shaders
        ##        print "Compiling Update Shader"
        self.update_shader = glLibShader()
        self.update_shader.use_prebuilt(GLLIB_CLOTH_UPDATE)
        ##        print "Compiling Collision Shader"
        self.collision_shader = glLibShader()
        self.collision_shader.use_prebuilt(GLLIB_CLOTH_COLLIDE)
        ##        print "Compiling Normal Shader"
        self.normal_shader = glLibShader()
        self.normal_shader.use_prebuilt(GLLIB_CLOTH_NORMAL)
        ##        print "Compiling Draw Shader"
        self.draw_shader = glLibShader()
        self.draw_shader.use_prebuilt(GLLIB_CLOTH_DRAW)
        ##        print "Compiling Distance Shader"
        self.dist_shader = glLibShader()
        self.dist_shader.use_prebuilt(GLLIB_CLOTH_DISTANCE)
        ##        self.update_shader.save_vertex()

        # Get Target Distances
        self.glLibInternal_push()
        self.dist_angle_framebuffer.enable([1, 2])
        self.glLibInternal_use_dist_shader()
        self.dist_shader.pass_float("stretched", stretched)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        self.view_2d.set_view()
        self.particles.draw()
        glLibUseShader(None)
        self.dist_angle_framebuffer.disable()
        self.glLibInternal_pop()
        self.dist_edges_tex = self.dist_angle_framebuffer.get_texture(1)
        self.dist_corners_tex = self.dist_angle_framebuffer.get_texture(2)

        # Initialize Position
        self.glLibInternal_initialize_position()
Beispiel #4
0
    def __init__(self, res):
        #heavily based on http://http.developer.nvidia.com/GPUGems/gpugems_ch38.html

        self.res = list(res)
        self.dimensions = len(self.res)
        self.grid_delta = vec_div([1.0] * self.dimensions, self.res)
        self.diff = 0.0
        self.visc = 0.0

        self.new_forces = []
        self.new_densities = []

        self.view2D = glLibView2D((0, 0, self.res[0], self.res[1]))

        self.precis = 32

        self.texture_captions = {}
        self.font = pygame.font.SysFont("Times New Roman", 10)

        if self.dimensions == 3: glEnable(GL_TEXTURE_3D)
        self.gas_fbo1 = glLibFBO(self.res)
        self.gas_fbo2 = glLibFBO(self.res)
        self.prs_fbo1 = glLibFBO(self.res)
        self.prs_fbo2 = glLibFBO(self.res)
        self.vel_fbo1 = glLibFBO(self.res)
        self.vel_fbo2 = glLibFBO(self.res)
        self.div_fbo1 = glLibFBO(self.res)
        self.div_fbo2 = glLibFBO(self.res)
        for fbo in [
                self.gas_fbo1, self.gas_fbo2, self.prs_fbo1, self.prs_fbo2,
                self.vel_fbo1, self.vel_fbo2, self.div_fbo1, self.div_fbo2
        ]:
            fbo.add_render_target(1,
                                  GLLIB_RGB,
                                  filtering=GLLIB_FILTER,
                                  precision=self.precis)
            fbo.textures[1].edge(GLLIB_CLAMP)

        self.gas_ping_pong = 1
        self.prs_ping_pong = 1
        self.vel_ping_pong = 1
        self.div_ping_pong = 1

        self.zero_value = np.empty(tuple(self.res) + (3, ))
        self.zero_value.fill(0.5)
        self.reset()
        if self.dimensions == 3: glDisable(GL_TEXTURE_3D)

        self.advection_shader = glLibShader()
        if self.dimensions == 2:
            self.advection_shader.user_variables("""
            uniform float dt;
            const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                                 str(self.res[1]) + """);
            const vec2 griddelta = 1.0/gridsize;""")
            self.advection_shader.render_equation("""
            //follow the velocity field "back in time"
            vec2 pos = uv - dt*griddelta*(texture2D(tex2D_1,uv).rg-vec2(0.5));
            //sample the data texture there, and write to the current fragment
            color = texture2D(tex2D_2,pos);""")
        elif self.dimensions == 3:
            self.advection_shader.user_variables("""
            uniform float dt;
            const vec3 gridsize = vec3(""" + str(self.res[0]) + "," +
                                                 str(self.res[1]) + "," +
                                                 str(self.res[2]) + """);
            const vec3 griddelta = 1.0/gridsize;""")
            self.advection_shader.render_equation("""
            //follow the velocity field "back in time"
            vec3 pos = uvw - dt*griddelta*(texture3D(tex3D_1,uvw).rgb-vec3(0.5));
            //sample the data texture there, and write to the current fragment
            color = texture3D(tex3D_2,pos);""")
            self.advection_shader.max_textures_3D(2)
        print("Advection Shader:")
        errors = self.advection_shader.compile()
        if errors != "": print(errors)

        self.vec_zero_shader = glLibShader()
        self.vec_zero_shader.render_equation("""
        color.rgb = vec3(0.5);""")
        print("Vector Zero Shader:")
        errors = self.vec_zero_shader.compile()
        if errors != "": print(errors)

        self.add_shader = glLibShader()
        self.add_shader.user_variables("uniform vec3 quantity;")
        if self.dimensions == 2:
            self.add_shader.render_equation("""
            //tex2D_1 contains the obstacles.  tex2D_2 contains the data field.
            color.rgb = texture2D(tex2D_2,uv).rgb;
            if (texture2D(tex2D_1,uv).r==0.0) { color.rgb += quantity; }""")
        elif self.dimensions == 3:
            self.add_shader.render_equation("""
            //tex3D_1 contains the obstacles.  tex3D_2 contains the data field.
            color.rgb = texture3D(tex3D_2,uvw).rgb;
            if (texture3D(tex3D_1,uvw).r==0.0) { color.rgb += quantity; }""")
            self.add_shader.max_textures_3D(2)
        print("Add Shader:")
        errors = self.add_shader.compile()
        if errors != "": print(errors)

        self.diffuse_shader = glLibShader()
        self.diffuse_shader.user_variables("""
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                           str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;""")
        self.diffuse_shader.render_equation("""
        //tex2D_1 contains the obstacles texture.  tex2D_2 contains the data texture
        vec3 q01 = texture2D(tex2D_2,uv-vec2(griddelta.x,0.0)).rgb;
        vec3 q21 = texture2D(tex2D_2,uv+vec2(griddelta.x,0.0)).rgb;
        vec3 q10 = texture2D(tex2D_2,uv-vec2(0.0,griddelta.y)).rgb;
        vec3 q12 = texture2D(tex2D_2,uv+vec2(0.0,griddelta.y)).rgb;
        vec3 q11 = texture2D(tex2D_2,uv                      ).rgb;
        color.rgb = q11;
        float total = 1.0;
        if (texture2D(tex2D_1,uv-vec2(griddelta.x,0.0)).r==0.0) { color.rgb += q01; total += 1.0; }
        if (texture2D(tex2D_1,uv+vec2(griddelta.x,0.0)).r==0.0) { color.rgb += q21; total += 1.0; }
        if (texture2D(tex2D_1,uv-vec2(0.0,griddelta.y)).r==0.0) { color.rgb += q10; total += 1.0; }
        if (texture2D(tex2D_1,uv+vec2(0.0,griddelta.y)).r==0.0) { color.rgb += q12; total += 1.0; }
        color.rgb /= total;
        //color.rgb = vec3(0.5) + -4.0*(q11-vec3(0.5)) + q01+q21 + q10+q12 - 4.0*vec3(0.5);"""
                                            )
        print("Diffuse Shader:")
        errors = self.diffuse_shader.compile()
        if errors != "": print(errors)

        self.div_shader = glLibShader()
        if self.dimensions == 2:
            self.div_shader.user_variables("""
            const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                           str(self.res[1]) + """);
            const vec2 griddelta = 1.0/gridsize;""")
            self.div_shader.render_equation("""
            //tex2D_1 contains velocity.  tex2D_2 contains the obstacles texture
            vec3 wL = texture2D(tex2D_1,uv-vec2(griddelta.x,0.0)).rgb;
            vec3 wR = texture2D(tex2D_1,uv+vec2(griddelta.x,0.0)).rgb;
            vec3 wB = texture2D(tex2D_1,uv-vec2(0.0,griddelta.y)).rgb;
            vec3 wT = texture2D(tex2D_1,uv+vec2(0.0,griddelta.y)).rgb;

            if (texture2D(tex2D_2,uv-vec2(griddelta.x,0.0)).r==1.0) { wL = vec3(0.5); }
            if (texture2D(tex2D_2,uv+vec2(griddelta.x,0.0)).r==1.0) { wR = vec3(0.5); }
            if (texture2D(tex2D_2,uv-vec2(0.0,griddelta.y)).r==1.0) { wB = vec3(0.5); }
            if (texture2D(tex2D_2,uv+vec2(0.0,griddelta.y)).r==1.0) { wT = vec3(0.5); }
            
            color.r = 0.5 + 0.5 * ((wR.x-wL.x)+(wT.y-wB.y));""")
        elif self.dimensions == 3:
            self.div_shader.user_variables("""
            const vec3 gridsize = vec3(""" + str(self.res[0]) + "," +
                                           str(self.res[1]) + "," +
                                           str(self.res[2]) + """);
            const vec3 griddelta = 1.0/gridsize;""")
            self.div_shader.render_equation("""
            //tex3D_1 contains velocity.  tex3D_2 contains the obstacles texture
            vec3 wxL = texture3D(tex3D_1,uvw-vec3(griddelta.x,0.0,0.0)).rgb;
            vec3 wxR = texture3D(tex3D_1,uvw+vec3(griddelta.x,0.0,0.0)).rgb;
            vec3 wyB = texture3D(tex3D_1,uvw-vec3(0.0,griddelta.y,0.0)).rgb;
            vec3 wyT = texture3D(tex3D_1,uvw+vec3(0.0,griddelta.y,0.0)).rgb;
            vec3 wzB = texture3D(tex3D_1,uvw-vec3(0.0,0.0,griddelta.z)).rgb;
            vec3 wzF = texture3D(tex3D_1,uvw+vec3(0.0,0.0,griddelta.z)).rgb;

            if (texture3D(tex3D_2,uvw-vec3(griddelta.x,0.0,0.0)).r==1.0) { wxL = vec3(0.5); }
            if (texture3D(tex3D_2,uvw+vec3(griddelta.x,0.0,0.0)).r==1.0) { wxR = vec3(0.5); }
            if (texture3D(tex3D_2,uvw-vec3(0.0,griddelta.y,0.0)).r==1.0) { wyB = vec3(0.5); }
            if (texture3D(tex3D_2,uvw+vec3(0.0,griddelta.y,0.0)).r==1.0) { wyT = vec3(0.5); }
            if (texture3D(tex3D_2,uvw-vec3(0.0,0.0,griddelta.z)).r==1.0) { wzB = vec3(0.5); }
            if (texture3D(tex3D_2,uvw+vec3(0.0,0.0,griddelta.z)).r==1.0) { wzF = vec3(0.5); }
            
            color.r = 0.5 + 0.5 * ((wxR.x-wxL.x)+(wyT.y-wyB.y)+(wzF.z-wzB.z));"""
                                            )
            self.div_shader.max_textures_3D(2)
        print("Divergence Shader:")
        errors = self.div_shader.compile()
        if errors != "": print(errors)

        self.prs_jacobi_shader = glLibShader()
        if self.dimensions == 2:
            self.prs_jacobi_shader.user_variables("""
            const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                                  str(self.res[1]) + """);
            const vec2 griddelta = 1.0/gridsize;
            const float alpha = 1.0;//-pow(griddelta.x,2.0);
            const float beta = 4.0;""")
            self.prs_jacobi_shader.render_equation("""
            //tex2D_1 contains x, the pressure.  tex2D_2 contains b, the divergence.  tex2D_3 contains the obstacles.
            float xC = texture2D(tex2D_1,uv                      ).r - 0.5;
            float xL = texture2D(tex2D_1,uv-vec2(griddelta.x,0.0)).r - 0.5;
            float xR = texture2D(tex2D_1,uv+vec2(griddelta.x,0.0)).r - 0.5;
            float xB = texture2D(tex2D_1,uv-vec2(0.0,griddelta.y)).r - 0.5;
            float xT = texture2D(tex2D_1,uv+vec2(0.0,griddelta.y)).r - 0.5;
            float bC = texture2D(tex2D_2,uv                      ).r - 0.5;
            
            if (texture2D(tex2D_3,uv-vec2(griddelta.x,0.0)).r==1.0) { xL = xC; }
            if (texture2D(tex2D_3,uv+vec2(griddelta.x,0.0)).r==1.0) { xR = xC; }
            if (texture2D(tex2D_3,uv-vec2(0.0,griddelta.y)).r==1.0) { xB = xC; }
            if (texture2D(tex2D_3,uv+vec2(0.0,griddelta.y)).r==1.0) { xT = xC; }

            //color.r = 0.5 + ((xL+xR+xB+xT+(alpha*bC))/beta);
            color.r = 0.5 + ((xL+xR+xB+xT-bC)/4.0);""")
        elif self.dimensions == 3:
            self.prs_jacobi_shader.user_variables("""
            const vec3 gridsize = vec3(""" + str(self.res[0]) + "," +
                                                  str(self.res[1]) + "," +
                                                  str(self.res[2]) + """);
            const vec3 griddelta = 1.0/gridsize;
            const float alpha = 1.0;
            const float beta = 6.0;""")
            self.prs_jacobi_shader.render_equation("""
            //tex3D_1 contains x, the pressure.  tex3D_2 contains b, the divergence.  tex3D_3 contains the obstacles.
            float xC = texture3D(tex3D_1,uvw                          ).r - 0.5;
            float xxL = texture3D(tex3D_1,uvw-vec3(griddelta.x,0.0,0.0)).r - 0.5;
            float xxR = texture3D(tex3D_1,uvw+vec3(griddelta.x,0.0,0.0)).r - 0.5;
            float xyB = texture3D(tex3D_1,uvw-vec3(0.0,griddelta.y,0.0)).r - 0.5;
            float xyT = texture3D(tex3D_1,uvw+vec3(0.0,griddelta.y,0.0)).r - 0.5;
            float xzB = texture3D(tex3D_1,uvw-vec3(0.0,0.0,griddelta.y)).r - 0.5;
            float xzF = texture3D(tex3D_1,uvw+vec3(0.0,0.0,griddelta.y)).r - 0.5;
            float bC = texture3D(tex3D_2,uvw                          ).r - 0.5;
            
            if (texture3D(tex3D_3,uvw-vec3(griddelta.x,0.0,0.0)).r==1.0) { xxL = xC; }
            if (texture3D(tex3D_3,uvw+vec3(griddelta.x,0.0,0.0)).r==1.0) { xxR = xC; }
            if (texture3D(tex3D_3,uvw-vec3(0.0,griddelta.y,0.0)).r==1.0) { xyB = xC; }
            if (texture3D(tex3D_3,uvw+vec3(0.0,griddelta.y,0.0)).r==1.0) { xyT = xC; }
            if (texture3D(tex3D_3,uvw-vec3(0.0,0.0,griddelta.z)).r==1.0) { xzB = xC; }
            if (texture3D(tex3D_3,uvw+vec3(0.0,0.0,griddelta.z)).r==1.0) { xzF = xC; }

            color.r = 0.5 + ((xxL+xxR+xyB+xyT+xzB+xzF-bC)/6.0);""")
            self.prs_jacobi_shader.max_textures_3D(3)
        print("Pressure Jacobi Shader:")
        errors = self.prs_jacobi_shader.compile()
        if errors != "": print(errors)

        self.velprs_proj_shader = glLibShader()
        if self.dimensions == 2:
            self.velprs_proj_shader.user_variables("""
            const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                                   str(self.res[1]) + """);
            const vec2 griddelta = 1.0/gridsize;""")
            self.velprs_proj_shader.render_equation("""
            //tex2D_1 contains the velocities.  tex2D_2 contains the pressure.  tex2D_3 contains the obstacles.
            float pC = texture2D(tex2D_2,uv                      ).r;
            float pL = texture2D(tex2D_2,uv-vec2(griddelta.x,0.0)).r;
            float pR = texture2D(tex2D_2,uv+vec2(griddelta.x,0.0)).r;
            float pB = texture2D(tex2D_2,uv-vec2(0.0,griddelta.y)).r;
            float pT = texture2D(tex2D_2,uv+vec2(0.0,griddelta.y)).r;

            if (texture2D(tex2D_3,uv-vec2(griddelta.x,0.0)).r==1.0) { pL = pC; }
            if (texture2D(tex2D_3,uv+vec2(griddelta.x,0.0)).r==1.0) { pR = pC; }
            if (texture2D(tex2D_3,uv-vec2(0.0,griddelta.y)).r==1.0) { pB = pC; }
            if (texture2D(tex2D_3,uv+vec2(0.0,griddelta.y)).r==1.0) { pT = pC; }

            color.xyz = texture2D(tex2D_1,uv).xyz;
            //subtract the gradient of the pressure from the velocity
            color.xy -= 0.5*vec2(pR-pL,pT-pB);""")
        elif self.dimensions == 3:
            self.velprs_proj_shader.user_variables("""
            const vec3 gridsize = vec3(""" + str(self.res[0]) + "," +
                                                   str(self.res[1]) + "," +
                                                   str(self.res[2]) + """);
            const vec3 griddelta = 1.0/gridsize;""")
            self.velprs_proj_shader.render_equation("""
            //tex3D_1 contains the velocities.  tex3D_2 contains the pressure.  tex3D_3 contains the obstacles.
            float pC  = texture3D(tex3D_2,uvw                          ).r;
            float pxL = texture3D(tex3D_2,uvw-vec3(griddelta.x,0.0,0.0)).r;
            float pxR = texture3D(tex3D_2,uvw+vec3(griddelta.x,0.0,0.0)).r;
            float pyB = texture3D(tex3D_2,uvw-vec3(0.0,griddelta.y,0.0)).r;
            float pyT = texture3D(tex3D_2,uvw+vec3(0.0,griddelta.y,0.0)).r;
            float pzB = texture3D(tex3D_2,uvw-vec3(0.0,0.0,griddelta.z)).r;
            float pzF = texture3D(tex3D_2,uvw+vec3(0.0,0.0,griddelta.z)).r;

            if (texture3D(tex3D_3,uvw-vec3(griddelta.x,0.0,0.0)).r==1.0) { pxL = pC; }
            if (texture3D(tex3D_3,uvw+vec3(griddelta.x,0.0,0.0)).r==1.0) { pxR = pC; }
            if (texture3D(tex3D_3,uvw-vec3(0.0,griddelta.y,0.0)).r==1.0) { pyB = pC; }
            if (texture3D(tex3D_3,uvw+vec3(0.0,griddelta.y,0.0)).r==1.0) { pyT = pC; }
            if (texture3D(tex3D_3,uvw-vec3(0.0,0.0,griddelta.z)).r==1.0) { pzB = pC; }
            if (texture3D(tex3D_3,uvw+vec3(0.0,0.0,griddelta.z)).r==1.0) { pzF = pC; }

            color.xyz = texture3D(tex3D_1,uvw).xyz;
            //subtract the gradient of the pressure from the velocity
            color.xyz -= 0.5*vec3(pxR-pxL,pyT-pyB,pzF-pzB);""")
            self.velprs_proj_shader.max_textures_3D(3)
        print("Velocity-Pressure Projection Shader:")
        errors = self.velprs_proj_shader.compile()
        if errors != "": print(errors)

        if self.dimensions == 3:
            ##            self.draw_shader = glLibShader()
            ##            self.draw_shader.user_variables("uniform float point_size;")
            ##            self.draw_shader.post_vertex("""
            ##            gl_PointSize = point_size/length(gl_Position);""")
            ##            self.draw_shader.render_equation("""
            ##            vec2 v_rot = normalize(vertex.zw);
            ##            vec4 l_uv = vec4(0.0,0.0,gl_PointCoord.xy);
            ##            l_uv.zw-=vec2(0.5,0.5);l_uv.x=l_uv.z*v_rot.x;l_uv.y=l_uv.w*v_rot.x;l_uv.x-=l_uv.w*v_rot.y;l_uv.y+=l_uv.z*v_rot.y;
            ##            //color.rgb = texture3D(tex3D_1,uvw).rgb;
            ##            color.rgb = vec3(1.0);
            ##            //color *= texture2D(tex2D_2,l_uv.xy+vec2(0.5,0.5));""")
            ##            self.draw_shader.max_textures_3D(1)
            ##            print "Draw Shader:"
            ##            errors = self.draw_shader.compile()
            ##            if errors != "": print errors
            ##
            ##            self.point_texture = glLibTexture2D("glLib/causticpoint.png",(0,0,83,83),GLLIB_RGBA)
            ##            self.point_texture.edge(GLLIB_CLAMP)
            self.volume_obj = glLibVolume(self.res)
Beispiel #5
0
    def __init__(self,pos_length_surf,grow_surf,length_scale,max_length,density):
        #Size
        self.size = list(pos_length_surf.get_size())

        #Misc.
        self.view_2d = glLibView2D((0,0,self.size[0],self.size[1]))
        self.update_pingpong = 1
        
        #Hair Parameters
        self.scale = 1.0
        self.trans = [0.0,0.0,0.0]
        self.dampening = 0.98
        self.tensor = 1.0
        self.gravity = [0.0,0.0,0.0]
        self.steps = 1
        self.density = density
        self.max_length = max_length
        self.length_scale = length_scale
        self.time_step = 1.0

        #Physics
        self.forces = [0.0,0.0,0.0]

        #Geometry
        self.particles = glLibGrid2D(self.size)
##        self.particles_mesh = glLibGrid2DMesh(self.size)
        self.particles_mesh = glLibDoubleGrid3DMesh([self.density*self.size[0],self.density*self.size[1],self.max_length])
##        self.particles_mesh = glLibDoubleGrid3DMesh([3,4,5])
        self.draw_particles = glLibGrid2D(sc_vec(self.density,self.size))
        
        #Textures
        self.position_length_textures = [glLibTexture2D(pos_length_surf,(0,0,self.size[0],self.size[1]),GL_RGBA,filtering=GLLIB_FILTER,precision=32)]
        self.grow_tex = glLibTexture2D(grow_surf,(0,0,self.size[0],self.size[1]),GL_RGB,precision=32)
        
        #FBOs
        self.update_framebuffers1 = []
        self.update_framebuffers2 = []
        self.grow_framebuffers = []
        for hair_segment in xrange(self.max_length):
            update_framebuffer1 = glLibFBO(self.size)
            update_framebuffer1.add_render_target(1,precision=32,filter=GLLIB_FILTER,type=GLLIB_RGBA)
            update_framebuffer1.add_render_target(2,precision=32,filter=GLLIB_FILTER)
            self.update_framebuffers1.append(update_framebuffer1)
            update_framebuffer2 = glLibFBO(self.size)
            update_framebuffer2.add_render_target(1,precision=32,filter=GLLIB_FILTER,type=GLLIB_RGBA)
            update_framebuffer2.add_render_target(2,precision=32,filter=GLLIB_FILTER)
            self.update_framebuffers2.append(update_framebuffer2)
            grow_framebuffer = glLibFBO(self.size)
            grow_framebuffer.add_render_target(1,precision=32,type=GLLIB_RGBA)
            self.grow_framebuffers.append(grow_framebuffer)

        #Shaders
        self.grow_shader = glLibShader()
        self.grow_shader.use_prebuilt(GLLIB_HAIR_GROW)
        self.update_shader = glLibShader()
        self.update_shader.use_prebuilt(GLLIB_HAIR_UPDATE)
        self.draw_shader = glLibShader()
        self.draw_shader.use_prebuilt(GLLIB_HAIR_DRAW)

        #Grow Hair
        self.glLibInternal_grow()

        #Initialize Position
        self.glLibInternal_initialize_position()
    def __init__(self, res):
        #heavily based on http://http.developer.nvidia.com/GPUGems/gpugems_ch38.html

        self.res = list(res)
        self.diff = 0.0
        self.visc = 0.0

        self.new_forces = []
        self.new_densities = []

        self.view2D = glLibView2D((0, 0, self.res[0], self.res[1]))

        self.particles = glLibGrid3D([self.res[0], self.res[1], 4])
        ##        self.particles = glLibGrid3D([self.res[0]/4,self.res[1]/4,4])

        ##        print glLibGrid3D([2,2,4]).vertex_vbo.data

        self.precis = 32

        self.texture_captions = {}
        self.font = pygame.font.SysFont("Times New Roman", 10)

        self.gas_fbo1 = glLibFBO((self.res[0], self.res[1]))
        self.gas_fbo2 = glLibFBO((self.res[0], self.res[1]))
        self.gas_fbo1.add_render_target(1,
                                        GLLIB_RGB,
                                        filtering=GLLIB_FILTER,
                                        precision=self.precis)
        self.gas_fbo2.add_render_target(1,
                                        GLLIB_RGB,
                                        filtering=GLLIB_FILTER,
                                        precision=self.precis)
        self.gas_fbo1.textures[1].edge(GLLIB_CLAMP)
        self.gas_fbo2.textures[1].edge(GLLIB_CLAMP)

        self.prs_fbo1 = glLibFBO((self.res[0], self.res[1]))
        self.prs_fbo2 = glLibFBO((self.res[0], self.res[1]))
        self.prs_fbo1.add_render_target(1,
                                        GLLIB_RGB,
                                        filtering=GLLIB_FILTER,
                                        precision=self.precis)
        self.prs_fbo2.add_render_target(1,
                                        GLLIB_RGB,
                                        filtering=GLLIB_FILTER,
                                        precision=self.precis)
        self.prs_fbo1.textures[1].edge(GLLIB_CLAMP)
        self.prs_fbo2.textures[1].edge(GLLIB_CLAMP)

        self.vel_fbo1 = glLibFBO((self.res[0], self.res[1]))
        self.vel_fbo2 = glLibFBO((self.res[0], self.res[1]))
        self.vel_fbo1.add_render_target(1, GLLIB_RGB, precision=self.precis)
        self.vel_fbo2.add_render_target(1, GLLIB_RGB, precision=self.precis)
        self.vel_fbo1.textures[1].edge(GLLIB_CLAMP)
        self.vel_fbo2.textures[1].edge(GLLIB_CLAMP)

        self.div_fbo1 = glLibFBO((self.res[0], self.res[1]))
        self.div_fbo2 = glLibFBO((self.res[0], self.res[1]))
        self.div_fbo1.add_render_target(1, GLLIB_RGB, precision=self.precis)
        self.div_fbo2.add_render_target(1, GLLIB_RGB, precision=self.precis)
        self.div_fbo1.textures[1].edge(GLLIB_CLAMP)
        self.div_fbo2.textures[1].edge(GLLIB_CLAMP)

        self.gas_ping_pong = 1
        self.prs_ping_pong = 1
        self.vel_ping_pong = 1
        self.div_ping_pong = 1

        zero_value = np.empty((self.res[0], self.res[1], 3))
        zero_value.fill(0.5)

        self.vel_tex = glLibTexture2D(zero_value,
                                      GLLIB_ALL,
                                      GLLIB_RGB,
                                      precision=self.precis)
        self.gas_tex = glLibTexture2D(pygame.Surface(self.res),
                                      GLLIB_ALL,
                                      GLLIB_RGB,
                                      filtering=GLLIB_FILTER,
                                      precision=self.precis)
        self.prs_tex = glLibTexture2D(zero_value,
                                      GLLIB_ALL,
                                      GLLIB_RGB,
                                      filtering=GLLIB_FILTER,
                                      precision=self.precis)

        self.advection_shader = glLibShader()
        self.advection_shader.user_variables("""
        //tex2D_1 contains the velocities; tex2D_2 contains the quantity to be advected
        uniform float dt;
        uniform float pos_neg;
        varying vec3 sc;
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                             str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;""")
        self.advection_shader.vertex_extension_functions("""
        vec2 refl(float component, float low, float high) {
            if (component>high) { return vec2(2.0*high-component,-1.0); }
            if (component<low) { return vec2(2.0*low-component,-1.0); }
            return vec2(component,1.0);
        }""")
        self.advection_shader.vertex_transform("""
        vertex.xy *= vec2(1.0) - griddelta;
        vertex.xy += 0.5 * griddelta;
        gl_TexCoord[0].st = vertex.xy;
        vertex.xy *= vec2(""" + str(self.res[0]) + "," + str(self.res[1]) +
                                               """);
        vec2 delta = dt * vec3(texture2D(tex2D_1,gl_TexCoord[0].st).rgb-vec3(0.5)).rg;
        
        vec2 bottom = floor(delta);
        vec2 top = bottom + vec2(1.0);
        vec2 part = delta - bottom;
        sc = vec3(0.0);
        if      (vertex.z==0.0) { sc=vec3((1.0-part.x)*(1.0-part.y)); vertex.x+=bottom.x; vertex.y+=bottom.y; } //vertex.z == 0.0
        else if (vertex.z==1.0) { sc=vec3(     part.x *(1.0-part.y)); vertex.x+=   top.x; vertex.y+=bottom.y; } //vertex.z == 1.0
        else if (vertex.z <0.5) { sc=vec3((1.0-part.x)*     part.y ); vertex.x+=bottom.x; vertex.y+=   top.y; } //vertex.z == 1/3
        else if (vertex.z >0.5) { sc=vec3(     part.x *     part.y ); vertex.x+=   top.x; vertex.y+=   top.y; } //vertex.z == 2/3
        //vec2 x_refl = refl(vertex.x,0.0,""" + str(float(self.res[0])) + """);
        //vec2 y_refl = refl(vertex.y,0.0,""" + str(float(self.res[1])) + """);
        //vec2 z_refl = refl(vertex.z,0.0,""" + str(1.0) + """);
        //vertex.xyz = vec3(x_refl.x,y_refl.x,z_refl.x);
        //sc        *= vec3(x_refl.y,y_refl.y,z_refl.y);""")
        self.advection_shader.render_equation("""
        color.rgb = texture2D(tex2D_2,uv).rgb;
        if (pos_neg!=0.0) {
            color.rgb = pos_neg * (color.rgb-vec3(0.5));
        }
        color.rgb *= sc;""")
        print "Advection Shader:"
        errors = self.advection_shader.compile()
        if errors != "": print errors

        self.vec_zero_shader = glLibShader()
        self.vec_zero_shader.render_equation("""
        color.rgb = vec3(0.5);""")
        print "Vector Zero Shader:"
        errors = self.vec_zero_shader.compile()
        if errors != "": print errors

        self.add_shader = glLibShader()
        self.add_shader.user_variables("uniform vec3 quantity;")
        self.add_shader.render_equation("""
        color.rgb = texture2D(tex2D_1,uv).rgb + quantity;""")
        print "Add Shader:"
        errors = self.add_shader.compile()
        if errors != "": print errors

        self.diffuse_shader = glLibShader()
        self.diffuse_shader.user_variables("""
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                           str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;""")
        self.diffuse_shader.render_equation("""
        vec3 q01 = texture2D(tex2D_1,uv-vec2(griddelta.x,0.0)).rgb;
        vec3 q21 = texture2D(tex2D_1,uv+vec2(griddelta.x,0.0)).rgb;
        vec3 q10 = texture2D(tex2D_1,uv-vec2(0.0,griddelta.y)).rgb;
        vec3 q12 = texture2D(tex2D_1,uv+vec2(0.0,griddelta.y)).rgb;
        vec3 q11 = texture2D(tex2D_1,uv                      ).rgb;
        color.rgb = q11 + q01+q21 + q10+q12;
        color.rgb /= 5.0;
        //color.rgb = -4.0*q11 + q01+q21 + q10+q12;""")
        print "Diffuse Shader:"
        errors = self.diffuse_shader.compile()
        if errors != "": print errors

        self.div_shader = glLibShader()
        self.div_shader.user_variables("""
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                       str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;
        const float halfrdx = 1.0;//0.5 * griddelta.x;""")
        self.div_shader.render_equation("""
        vec3 wL = texture2D(tex2D_1,uv-vec2(griddelta.x,0.0)).rgb;
        vec3 wR = texture2D(tex2D_1,uv+vec2(griddelta.x,0.0)).rgb;
        vec3 wB = texture2D(tex2D_1,uv-vec2(0.0,griddelta.y)).rgb;
        vec3 wT = texture2D(tex2D_1,uv+vec2(0.0,griddelta.y)).rgb;
        color.rgb = vec3(  0.5 + halfrdx * ((wR.x-wL.x)+(wT.y-wB.y))  );
        //color.rgb = vec3( (wR.x-wL.x), (wT.y-wB.y), 0.0 );""")
        print "Divergence Shader:"
        errors = self.div_shader.compile()
        if errors != "": print errors

        self.prs_jacobi_shader = glLibShader()
        self.prs_jacobi_shader.user_variables("""
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                              str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;
        const float alpha = 1.0;//-pow(griddelta.x,2.0);
        const float beta = 4.0;""")
        self.prs_jacobi_shader.render_equation("""
        //tex2D_1 contains x, the pressure.  tex2D_2 contains b, the divergence
        float xL = texture2D(tex2D_1,uv-vec2(griddelta.x,0.0)).r - 0.5;
        float xR = texture2D(tex2D_1,uv+vec2(griddelta.x,0.0)).r - 0.5;
        float xB = texture2D(tex2D_1,uv-vec2(0.0,griddelta.y)).r - 0.5;
        float xT = texture2D(tex2D_1,uv+vec2(0.0,griddelta.y)).r - 0.5;
        float bC = texture2D(tex2D_2,uv                      ).r - 0.5;

        //Evaluate Jacobi iteration
        color.rgb = vec3(  0.5 + ((xL+xR+xB+xT+(alpha*bC))/beta)  );""")
        print "Pressure Jacobi Shader:"
        errors = self.prs_jacobi_shader.compile()
        if errors != "": print errors

        self.velprs_proj_shader = glLibShader()
        self.velprs_proj_shader.user_variables("""
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                               str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;""")
        self.velprs_proj_shader.render_equation("""
        //tex2D_1 contains the velocities.  tex2D_2 contains the pressure
        float pL = texture2D(tex2D_2,uv-vec2(griddelta.x,0.0)).x;
        float pR = texture2D(tex2D_2,uv+vec2(griddelta.x,0.0)).x;
        float pB = texture2D(tex2D_2,uv-vec2(0.0,griddelta.y)).x;
        float pT = texture2D(tex2D_2,uv+vec2(0.0,griddelta.y)).x;
        color.xyz = texture2D(tex2D_1,uv).xyz;
        color.xy += 0.5*vec2(pR-pL,pT-pB);""")
        print "Velocity-Pressure Projection Shader:"
        errors = self.velprs_proj_shader.compile()
        if errors != "": print errors

        self.boundary_condition_shader = glLibShader()
        self.boundary_condition_shader.user_variables("""
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                                      str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;
        uniform vec3 offset;
        uniform float scale;""")
        self.boundary_condition_shader.render_equation("""
        //tex2D_1 is the state field (the field to set boundary conditions on)
        color.rgb = vec3(0.5) + scale*(texture2D(tex2D_1,uv+offset.xy*griddelta).rgb-vec3(0.5));"""
                                                       )
        print "Boundary Condition Shader:"
        errors = self.boundary_condition_shader.compile()
        if errors != "": print errors
Beispiel #7
0
    def __init__(self, pos_length_surf, grow_surf, length_scale, max_length,
                 density):
        #Size
        self.size = list(pos_length_surf.get_size())

        #Misc.
        self.view_2d = glLibView2D((0, 0, self.size[0], self.size[1]))
        self.update_pingpong = 1

        #Hair Parameters
        self.scale = 1.0
        self.trans = [0.0, 0.0, 0.0]
        self.dampening = 0.98
        self.tensor = 1.0
        self.gravity = [0.0, 0.0, 0.0]
        self.steps = 1
        self.density = density
        self.max_length = max_length
        self.length_scale = length_scale
        self.time_step = 1.0

        #Physics
        self.forces = [0.0, 0.0, 0.0]

        #Geometry
        self.particles = glLibGrid2D(self.size)
        ##        self.particles_mesh = glLibGrid2DMesh(self.size)
        self.particles_mesh = glLibDoubleGrid3DMesh([
            self.density * self.size[0], self.density * self.size[1],
            self.max_length
        ])
        ##        self.particles_mesh = glLibDoubleGrid3DMesh([3,4,5])
        self.draw_particles = glLibGrid2D(sc_vec(self.density, self.size))

        #Textures
        self.position_length_textures = [
            glLibTexture2D(pos_length_surf, (0, 0, self.size[0], self.size[1]),
                           GL_RGBA,
                           filtering=GLLIB_FILTER,
                           precision=32)
        ]
        self.grow_tex = glLibTexture2D(grow_surf,
                                       (0, 0, self.size[0], self.size[1]),
                                       GL_RGB,
                                       precision=32)

        #FBOs
        self.update_framebuffers1 = []
        self.update_framebuffers2 = []
        self.grow_framebuffers = []
        for hair_segment in xrange(self.max_length):
            update_framebuffer1 = glLibFBO(self.size)
            update_framebuffer1.add_render_target(1,
                                                  precision=32,
                                                  filter=GLLIB_FILTER,
                                                  type=GLLIB_RGBA)
            update_framebuffer1.add_render_target(2,
                                                  precision=32,
                                                  filter=GLLIB_FILTER)
            self.update_framebuffers1.append(update_framebuffer1)
            update_framebuffer2 = glLibFBO(self.size)
            update_framebuffer2.add_render_target(1,
                                                  precision=32,
                                                  filter=GLLIB_FILTER,
                                                  type=GLLIB_RGBA)
            update_framebuffer2.add_render_target(2,
                                                  precision=32,
                                                  filter=GLLIB_FILTER)
            self.update_framebuffers2.append(update_framebuffer2)
            grow_framebuffer = glLibFBO(self.size)
            grow_framebuffer.add_render_target(1,
                                               precision=32,
                                               type=GLLIB_RGBA)
            self.grow_framebuffers.append(grow_framebuffer)

        #Shaders
        self.grow_shader = glLibShader()
        self.grow_shader.use_prebuilt(GLLIB_HAIR_GROW)
        self.update_shader = glLibShader()
        self.update_shader.use_prebuilt(GLLIB_HAIR_UPDATE)
        self.draw_shader = glLibShader()
        self.draw_shader.use_prebuilt(GLLIB_HAIR_DRAW)

        #Grow Hair
        self.glLibInternal_grow()

        #Initialize Position
        self.glLibInternal_initialize_position()
    def __init__(self,res):
        #heavily based on http://http.developer.nvidia.com/GPUGems/gpugems_ch38.html
        
        self.res = list(res)
        self.diff = 0.0
        self.visc = 0.0

        self.new_forces = []
        self.new_densities = []

        self.view2D = glLibView2D((0,0,self.res[0],self.res[1]))

        self.precis = 32

        self.advection_fbo1 = glLibFBO((self.res[0],self.res[1]))
        self.advection_fbo2 = glLibFBO((self.res[0],self.res[1]))
        self.advection_fbo1.add_render_target(1,GLLIB_RGB,GLLIB_FILTER,precision=self.precis)
        self.advection_fbo2.add_render_target(1,GLLIB_RGB,GLLIB_FILTER,precision=self.precis)
        
        self.diffusion_jacobi_fbo1 = glLibFBO((self.res[0],self.res[1]))
        self.diffusion_jacobi_fbo2 = glLibFBO((self.res[0],self.res[1]))
        self.diffusion_jacobi_fbo1.add_render_target(1,GLLIB_RGB,GLLIB_FILTER,precision=self.precis)
        self.diffusion_jacobi_fbo2.add_render_target(1,GLLIB_RGB,GLLIB_FILTER,precision=self.precis)
        
        self.add_fbo1 = glLibFBO((self.res[0],self.res[1]))
        self.add_fbo2 = glLibFBO((self.res[0],self.res[1]))
        self.add_fbo1.add_render_target(1,GLLIB_RGB,GLLIB_FILTER,precision=self.precis)
        self.add_fbo2.add_render_target(1,GLLIB_RGB,GLLIB_FILTER,precision=self.precis)
        
        self.pressure_fbo = glLibFBO((self.res[0],self.res[1]))
        self.pressure_fbo.add_render_target(1,GLLIB_RGB,GLLIB_FILTER,precision=self.precis)

        self.pressure_jacobi_fbo1 = glLibFBO((self.res[0],self.res[1]))
        self.pressure_jacobi_fbo2 = glLibFBO((self.res[0],self.res[1]))
        self.pressure_jacobi_fbo1.add_render_target(1,GLLIB_RGB,GLLIB_FILTER,precision=self.precis)
        self.pressure_jacobi_fbo2.add_render_target(1,GLLIB_RGB,GLLIB_FILTER,precision=self.precis)
        
        self.spressure_fbo = glLibFBO((self.res[0],self.res[1]))
        self.spressure_fbo.add_render_target(1,GLLIB_RGB,GLLIB_FILTER,precision=self.precis)

        self.advection_ping_pong = 1
        self.add_ping_pong = 1
        self.diffusion_jacobi_ping_pong = 1
        self.pressure_jacobi_ping_pong = 1

        zero_value = np.empty((self.res[0],self.res[1],3))
        zero_value.fill(127.5)
        zero_value = pygame.surfarray.make_surface(zero_value)
        
        self.velocity_tex = glLibTexture2D(zero_value,GLLIB_ALL,GLLIB_RGB,GLLIB_FILTER,precision=32)

        self.gas_tex = glLibTexture2D(pygame.Surface(self.res),GLLIB_ALL,GLLIB_RGB,GLLIB_FILTER,precision=32)

        self.advection_shader = glLibShader()
        self.advection_shader.user_variables("""
        uniform float dt;
        const vec2 gridsize = vec2("""+str(self.res[0])+","+str(self.res[1])+""");
        const vec2 griddelta = 1.0/gridsize;""")
        self.advection_shader.render_equation("""
        //follow the velocity field "back in time", then interpolate and write to the output fragment
        //tex2D_1 contains the velocities; tex2D_2 contains the quantity to be advected
        vec2 pos = uv - dt * griddelta * vec3(texture2D(tex2D_1,uv).rgb-vec3(0.5)).rg;
        color.rgb = texture2D(tex2D_2,pos).rgb;""")
        print "Advection Shader"
        print self.advection_shader.compile()

        self.jacobi_shader = glLibShader()
        self.jacobi_shader.user_variables("""
        uniform float iterations;
        uniform float dt;
        const vec2 gridsize = vec2("""+str(self.res[0])+","+str(self.res[1])+""");
        const vec2 griddelta = 1.0/gridsize;
        float alpha = griddelta.x*griddelta.y/(iterations*dt);
        float rBeta = 1.0/(4.0+alpha);""")
        self.jacobi_shader.render_equation("""
        //Ax = b; tex2D_1 contains the x vector; tex2D_2 contains the b vector
        
        //left, right, bottom, and top x samples
        vec4 xL = texture2D(tex2D_1,uv-vec2(griddelta.x,0));
        vec4 xR = texture2D(tex2D_1,uv+vec2(griddelta.x,0));
        vec4 xB = texture2D(tex2D_1,uv-vec2(0,griddelta.y));
        vec4 xT = texture2D(tex2D_1,uv+vec2(0,griddelta.y));
        //b sample, from center
        vec4 bC = texture2D(tex2D_2,uv);

        // evaluate Jacobi iteration
        color = (xL + xR + xB + xT + alpha * bC) * rBeta;""")
        print "Jacobi Shader"
        print self.jacobi_shader.compile()

        self.divergence_shader = glLibShader()
        self.divergence_shader.user_variables("""
        uniform float iterations;
        uniform float dt;
        const vec2 gridsize = vec2("""+str(self.res[0])+","+str(self.res[1])+""");
        const vec2 griddelta = 1.0/gridsize;
        const float halfrdx = 0.5*griddelta.x;""")
        self.divergence_shader.render_equation("""
        //tex2D_1 contains the w vector field
        vec4 wL = texture2D(tex2D_1,uv-vec2(griddelta.x,0.0));
        vec4 wR = texture2D(tex2D_1,uv+vec2(griddelta.x,0.0));
        vec4 wB = texture2D(tex2D_1,uv-vec2(0.0,griddelta.y));
        vec4 wT = texture2D(tex2D_1,uv+vec2(0.0,griddelta.y));

        color.rgb = vec3(  halfrdx * ((wR.x-wL.x)+(wT.y-wB.y))  );
        color.rgb += 0.5;""")
        print "Divergence Shader"
        print self.divergence_shader.compile()

        self.gradient_subtract_shader = glLibShader()
        self.gradient_subtract_shader.user_variables("""
        const vec2 gridsize = vec2("""+str(self.res[0])+","+str(self.res[1])+""");
        const vec2 griddelta = 1.0/gridsize;
        const float halfrdx = 0.5*griddelta.x;""")
        self.gradient_subtract_shader.render_equation("""
        //tex2D_1 contains the pressure; tex2D_2 contains the velocity
        float pL = texture2D(tex2D_1,uv-vec2(griddelta.x,0.0)).r;
        float pR = texture2D(tex2D_1,uv+vec2(griddelta.x,0.0)).r;
        float pB = texture2D(tex2D_1,uv-vec2(0.0,griddelta.y)).r;
        float pT = texture2D(tex2D_1,uv+vec2(0.0,griddelta.y)).r;

        color.rgb = texture2D(tex2D_2,uv).rgb;
        color.rg -= halfrdx * vec2(pR-pL,pT-pB);""")
        print "Gradient Subtract Shader"
        print self.gradient_subtract_shader.compile()

        self.add_shader = glLibShader()
        self.add_shader.user_variables("uniform vec3 quantity;")
        self.add_shader.render_equation("""
        color.rgb = texture2D(tex2D_1,uv).rgb + quantity;""")
        print "Add Shader"
        print self.add_shader.compile()
    def __init__(self, res):
        #heavily based on http://http.developer.nvidia.com/GPUGems/gpugems_ch38.html

        self.res = list(res)
        self.diff = 0.0
        self.visc = 0.0

        self.new_forces = []
        self.new_densities = []

        self.view2D = glLibView2D((0, 0, self.res[0], self.res[1]))

        self.precis = 32

        self.texture_captions = {}
        self.font = pygame.font.SysFont("Times New Roman", 10)

        self.gas_fbo1 = glLibFBO((self.res[0], self.res[1]))
        self.gas_fbo2 = glLibFBO((self.res[0], self.res[1]))
        self.prs_fbo1 = glLibFBO((self.res[0], self.res[1]))
        self.prs_fbo2 = glLibFBO((self.res[0], self.res[1]))
        self.vel_fbo1 = glLibFBO((self.res[0], self.res[1]))
        self.vel_fbo2 = glLibFBO((self.res[0], self.res[1]))
        self.div_fbo1 = glLibFBO((self.res[0], self.res[1]))
        self.div_fbo2 = glLibFBO((self.res[0], self.res[1]))
        for fbo in [
                self.gas_fbo1, self.gas_fbo2, self.prs_fbo1, self.prs_fbo2,
                self.vel_fbo1, self.vel_fbo2, self.div_fbo1, self.div_fbo2
        ]:
            fbo.add_render_target(1,
                                  GLLIB_RGB,
                                  filtering=GLLIB_FILTER,
                                  precision=self.precis)
            fbo.textures[1].edge(GLLIB_CLAMP)

        self.gas_ping_pong = 1
        self.prs_ping_pong = 1
        self.vel_ping_pong = 1
        self.div_ping_pong = 1

        self.zero_value = np.empty((self.res[0], self.res[1], 3))
        self.zero_value.fill(0.5)
        self.reset()

        self.advection_shader = glLibShader()
        self.advection_shader.user_variables("""
        uniform float dt;
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                             str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;""")
        self.advection_shader.render_equation("""
        //follow the velocity field "back in time"
        vec2 pos = uv - dt*griddelta*(texture2D(tex2D_1,uv).rg-vec2(0.5));
        //sample the data texture there, and write to the current fragment
        color = texture2D(tex2D_2,pos);""")
        print "Advection Shader:"
        errors = self.advection_shader.compile()
        if errors != "": print errors

        self.vec_zero_shader = glLibShader()
        self.vec_zero_shader.render_equation("""
        color.rgb = vec3(0.5);""")
        print "Vector Zero Shader:"
        errors = self.vec_zero_shader.compile()
        if errors != "": print errors

        self.add_shader = glLibShader()
        self.add_shader.user_variables("uniform vec3 quantity;")
        self.add_shader.render_equation("""
        //tex2D_1 contains the obstacles.  tex2D_2 contains the data field.
        color.rgb = texture2D(tex2D_2,uv).rgb;
        if (texture2D(tex2D_1,uv).r==0.0) { color.rgb += quantity; }""")
        print "Add Shader:"
        errors = self.add_shader.compile()
        if errors != "": print errors

        self.diffuse_shader = glLibShader()
        self.diffuse_shader.user_variables("""
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                           str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;""")
        self.diffuse_shader.render_equation("""
        //tex2D_1 contains the obstacles texture.  tex2D_2 contains the data texture
        vec3 q01 = texture2D(tex2D_2,uv-vec2(griddelta.x,0.0)).rgb;
        vec3 q21 = texture2D(tex2D_2,uv+vec2(griddelta.x,0.0)).rgb;
        vec3 q10 = texture2D(tex2D_2,uv-vec2(0.0,griddelta.y)).rgb;
        vec3 q12 = texture2D(tex2D_2,uv+vec2(0.0,griddelta.y)).rgb;
        vec3 q11 = texture2D(tex2D_2,uv                      ).rgb;
        color.rgb = q11;
        float total = 1.0;
        if (texture2D(tex2D_1,uv-vec2(griddelta.x,0.0)).r==0.0) { color.rgb += q01; total += 1.0; }
        if (texture2D(tex2D_1,uv+vec2(griddelta.x,0.0)).r==0.0) { color.rgb += q21; total += 1.0; }
        if (texture2D(tex2D_1,uv-vec2(0.0,griddelta.y)).r==0.0) { color.rgb += q10; total += 1.0; }
        if (texture2D(tex2D_1,uv+vec2(0.0,griddelta.y)).r==0.0) { color.rgb += q12; total += 1.0; }
        color.rgb /= total;
        //color.rgb = vec3(0.5) + -4.0*(q11-vec3(0.5)) + q01+q21 + q10+q12 - 4.0*vec3(0.5);"""
                                            )
        print "Diffuse Shader:"
        errors = self.diffuse_shader.compile()
        if errors != "": print errors

        self.div_shader = glLibShader()
        self.div_shader.user_variables("""
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                       str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;""")
        self.div_shader.render_equation("""
        //tex2D_1 contains velocity.  tex2D_2 contains the obstacles texture
        vec3 wL = texture2D(tex2D_1,uv-vec2(griddelta.x,0.0)).rgb;
        vec3 wR = texture2D(tex2D_1,uv+vec2(griddelta.x,0.0)).rgb;
        vec3 wB = texture2D(tex2D_1,uv-vec2(0.0,griddelta.y)).rgb;
        vec3 wT = texture2D(tex2D_1,uv+vec2(0.0,griddelta.y)).rgb;

        if (texture2D(tex2D_2,uv-vec2(griddelta.x,0.0)).r==1.0) { wL = vec3(0.5); }
        if (texture2D(tex2D_2,uv+vec2(griddelta.x,0.0)).r==1.0) { wR = vec3(0.5); }
        if (texture2D(tex2D_2,uv-vec2(0.0,griddelta.y)).r==1.0) { wB = vec3(0.5); }
        if (texture2D(tex2D_2,uv+vec2(0.0,griddelta.y)).r==1.0) { wT = vec3(0.5); }
        
        color.r = 0.5 + 0.5 * ((wR.x-wL.x)+(wT.y-wB.y));""")
        print "Divergence Shader:"
        errors = self.div_shader.compile()
        if errors != "": print errors

        self.prs_jacobi_shader = glLibShader()
        self.prs_jacobi_shader.user_variables("""
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                              str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;
        const float alpha = 1.0;//-pow(griddelta.x,2.0);
        const float beta = 4.0;""")
        self.prs_jacobi_shader.render_equation("""
        //tex2D_1 contains x, the pressure.  tex2D_2 contains b, the divergence.  tex2D_3 contains the obstacles.
        float xC = texture2D(tex2D_1,uv                      ).r - 0.5;
        float xL = texture2D(tex2D_1,uv-vec2(griddelta.x,0.0)).r - 0.5;
        float xR = texture2D(tex2D_1,uv+vec2(griddelta.x,0.0)).r - 0.5;
        float xB = texture2D(tex2D_1,uv-vec2(0.0,griddelta.y)).r - 0.5;
        float xT = texture2D(tex2D_1,uv+vec2(0.0,griddelta.y)).r - 0.5;
        float bC = texture2D(tex2D_2,uv                      ).r - 0.5;
        
        if (texture2D(tex2D_3,uv-vec2(griddelta.x,0.0)).r==1.0) { xL = xC; }
        if (texture2D(tex2D_3,uv+vec2(griddelta.x,0.0)).r==1.0) { xR = xC; }
        if (texture2D(tex2D_3,uv-vec2(0.0,griddelta.y)).r==1.0) { xB = xC; }
        if (texture2D(tex2D_3,uv+vec2(0.0,griddelta.y)).r==1.0) { xT = xC; }

        //color.r = 0.5 + ((xL+xR+xB+xT+(alpha*bC))/beta);
        color.r = 0.5 + ((xL+xR+xB+xT-bC)/4.0);""")
        print "Pressure Jacobi Shader:"
        errors = self.prs_jacobi_shader.compile()
        if errors != "": print errors

        self.velprs_proj_shader = glLibShader()
        self.velprs_proj_shader.user_variables("""
        const vec2 gridsize = vec2(""" + str(self.res[0]) + "," +
                                               str(self.res[1]) + """);
        const vec2 griddelta = 1.0/gridsize;""")
        self.velprs_proj_shader.render_equation("""
        //tex2D_1 contains the velocities.  tex2D_2 contains the pressure.  tex2D_3 contains the obstacles.
        float pC = texture2D(tex2D_2,uv                      ).r;
        float pL = texture2D(tex2D_2,uv-vec2(griddelta.x,0.0)).r;
        float pR = texture2D(tex2D_2,uv+vec2(griddelta.x,0.0)).r;
        float pB = texture2D(tex2D_2,uv-vec2(0.0,griddelta.y)).r;
        float pT = texture2D(tex2D_2,uv+vec2(0.0,griddelta.y)).r;

        if (texture2D(tex2D_3,uv-vec2(griddelta.x,0.0)).r==1.0) { pL = pC; }
        if (texture2D(tex2D_3,uv+vec2(griddelta.x,0.0)).r==1.0) { pR = pC; }
        if (texture2D(tex2D_3,uv-vec2(0.0,griddelta.y)).r==1.0) { pB = pC; }
        if (texture2D(tex2D_3,uv+vec2(0.0,griddelta.y)).r==1.0) { pT = pC; }

        color.xyz = texture2D(tex2D_1,uv).xyz;
        //subtract the gradient of the pressure from the velocity
        color.xy -= 0.5*vec2(pR-pL,pT-pB);""")
        print "Velocity-Pressure Projection Shader:"
        errors = self.velprs_proj_shader.compile()
        if errors != "": print errors