Exemple #1
0
    def __enter__(self):
        """Loads the image data using OpenGL"""

        # Set image active in OpenGL
        ownit = self._blimg.bindcode[0] == 0
        if ownit:
            if self._blimg.gl_load() != 0:
                raise RuntimeError("failed to load image")
        previous_texture = self._get_integer(bgl.GL_TEXTURE_BINDING_2D)
        changed_state = (previous_texture != self._blimg.bindcode[0])
        if changed_state:
            bgl.glBindTexture(bgl.GL_TEXTURE_2D, self._blimg.bindcode[0])

        # Grab the image data
        self._width = self._get_tex_param(bgl.GL_TEXTURE_WIDTH, 0)
        self._height = self._get_tex_param(bgl.GL_TEXTURE_HEIGHT, 0)
        size = self._width * self._height * 4
        buf = bgl.Buffer(bgl.GL_BYTE, size)
        fmt = bgl.GL_BGRA if self._bgra else bgl.GL_RGBA
        bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, fmt, bgl.GL_UNSIGNED_BYTE, buf)

        # OpenGL returns the images upside down, so we're going to rotate it in memory.
        # ... But only if requested... :)
        if self._image_inverted:
            self._image_data = bytes(buf)
        else:
            self._image_data = self._invert_image(self._width, self._height, buf)

        # Restore previous OpenGL state
        if changed_state:
            bgl.glBindTexture(bgl.GL_TEXTURE_2D, previous_texture)
        if ownit:
            self._blimg.gl_free()
        return self
Exemple #2
0
def get_all_mipmaps(image, mm_offset=0):
    import bgl
    images = []

    image.gl_load()
    image_id = image.bindcode[0]
    if image_id == 0:
        return images
    level = mm_offset  # denetii - change this to shift the largest exported size down
    bgl.glBindTexture(bgl.GL_TEXTURE_2D, image_id)
    while level < 16:
        # LOG.debug('')
        buf = bgl.Buffer(bgl.GL_INT, 1)
        bgl.glGetTexLevelParameteriv(bgl.GL_TEXTURE_2D, level,
                                     bgl.GL_TEXTURE_WIDTH, buf)
        width = buf[0]
        # LOG.debug(width)
        if width < 8: break
        bgl.glGetTexLevelParameteriv(bgl.GL_TEXTURE_2D, level,
                                     bgl.GL_TEXTURE_HEIGHT, buf)
        height = buf[0]
        if height < 8: break
        del buf
        buf_size = width * height * 4
        # LOG.debug(buf_size)
        buf = bgl.Buffer(bgl.GL_BYTE, buf_size)
        bgl.glGetTexImage(bgl.GL_TEXTURE_2D, level, bgl.GL_RGBA,
                          bgl.GL_UNSIGNED_BYTE, buf)
        images.append((width, height, buf))
        if level == 0:
            pass  # LOG.debug(images[0][:16])
        # del buf
        level += 1
    return images
Exemple #3
0
    def get_level_data(self, level=0, calc_alpha=False, bgra=False, quiet=False, fast=False):
        """Gets the uncompressed pixel data for a requested mip level, optionally calculating the alpha
           channel from the image color data
        """
        width = self._get_tex_param(bgl.GL_TEXTURE_WIDTH, level)
        height = self._get_tex_param(bgl.GL_TEXTURE_HEIGHT, level)
        if not quiet:
            print("        Level #{}: {}x{}".format(level, width, height))

        # Grab the image data
        size = width * height * 4
        buf = bgl.Buffer(bgl.GL_BYTE, size)
        fmt = bgl.GL_BGRA if bgra else bgl.GL_RGBA
        bgl.glGetTexImage(bgl.GL_TEXTURE_2D, level, fmt, bgl.GL_UNSIGNED_BYTE, buf);
        if fast:
            return bytes(buf)

        # OpenGL returns the images upside down, so we're going to rotate it in memory.
        finalBuf = bytearray(size)
        row_stride = width * 4
        for i in range(height):
            src, dst = i * row_stride, (height - (i+1)) * row_stride
            finalBuf[dst:dst+row_stride] = buf[src:src+row_stride]

        # Do we need to calculate the alpha component?
        if calc_alpha:
            for i in range(0, size, 4):
                finalBuf[i+3] = int(sum(finalBuf[i:i+3]) / 3)
        return bytes(finalBuf)
Exemple #4
0
def get_image_buffer(path):
    img = load_image(path)
    if not img:
        return None
    sx, sy = img.size
    buf = bgl.Buffer(bgl.GL_FLOAT, 4 * sx * sy)
    img.gl_load(filter=bgl.GL_LINEAR, mag=bgl.GL_LINEAR)
    bgl.glBindTexture(bgl.GL_TEXTURE_2D, img.bindcode[0])
    bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, bgl.GL_FLOAT, buf)
    img.gl_free()
    img.user_clear()
    bpy.data.images.remove(img)
    return buf, sx, sy
Exemple #5
0
def get_image_buffer(path):
    img = load_image(path)
    if not img:
        return None
    sx, sy = img.size
    buf = bgl.Buffer(bgl.GL_FLOAT, 4 * sx * sy)
    img.gl_load(filter=bgl.GL_LINEAR, mag=bgl.GL_LINEAR)
    bgl.glBindTexture(bgl.GL_TEXTURE_2D, img.bindcode[0])
    bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0,
                      bgl.GL_RGBA, bgl.GL_FLOAT, buf)
    img.gl_free()
    img.user_clear()
    bpy.data.images.remove(img)
    return buf, sx, sy
Exemple #6
0
    def get_level_data(self,
                       level=0,
                       calc_alpha=False,
                       bgra=False,
                       report=None,
                       fast=False):
        """Gets the uncompressed pixel data for a requested mip level, optionally calculating the alpha
           channel from the image color data
        """
        width = self._get_tex_param(bgl.GL_TEXTURE_WIDTH, level)
        height = self._get_tex_param(bgl.GL_TEXTURE_HEIGHT, level)
        if report is not None:
            report.msg("Level #{}: {}x{}", level, width, height, indent=2)

        # Grab the image data
        size = width * height * 4
        buf = bgl.Buffer(bgl.GL_BYTE, size)
        fmt = bgl.GL_BGRA if bgra else bgl.GL_RGBA
        bgl.glGetTexImage(bgl.GL_TEXTURE_2D, level, fmt, bgl.GL_UNSIGNED_BYTE,
                          buf)
        if fast:
            return bytes(buf)

        # OpenGL returns the images upside down, so we're going to rotate it in memory.
        finalBuf = bytearray(size)
        row_stride = width * 4
        for i in range(height):
            src, dst = i * row_stride, (height - (i + 1)) * row_stride
            finalBuf[dst:dst + row_stride] = buf[src:src + row_stride]

        # If this is a detail map, then we need to bake that per-level here.
        if self._texkey.is_detail_map:
            detail_blend = self._texkey.detail_blend
            if detail_blend == TEX_DETAIL_ALPHA:
                self._make_detail_map_alpha(finalBuf, level)
            elif detail_blend == TEX_DETAIL_ADD:
                self._make_detail_map_alpha(finalBuf, level)
            elif detail_blend == TEX_DETAIL_MULTIPLY:
                self._make_detail_map_mult(finalBuf, level)

        # Do we need to calculate the alpha component?
        if calc_alpha:
            for i in range(0, size, 4):
                finalBuf[i + 3] = int(sum(finalBuf[i:i + 3]) / 3)
        return bytes(finalBuf)
Exemple #7
0
    def get_level_data(self, level=0, calc_alpha=False, bgra=False, quiet=False):
        """Gets the uncompressed pixel data for a requested mip level, optionally calculating the alpha
           channel from the image color data
        """
        width = self._get_tex_param(bgl.GL_TEXTURE_WIDTH, level)
        height = self._get_tex_param(bgl.GL_TEXTURE_HEIGHT, level)
        if not quiet:
            print("        Level #{}: {}x{}".format(level, width, height))

        # Grab the image data
        size = width * height * 4
        buf = bgl.Buffer(bgl.GL_BYTE, size)
        fmt = bgl.GL_BGRA if bgra else bgl.GL_RGBA
        bgl.glGetTexImage(bgl.GL_TEXTURE_2D, level, fmt, bgl.GL_UNSIGNED_BYTE, buf);

        # Calculate le alphas
        # NOTE: the variable names are correct for GL_RGBA. We'll still get the right values for
        # BGRA, obviously, but red will suddenly be... blue. Yeah.
        if calc_alpha:
            for i in range(0, size, 4):
                r, g, b = buf[i:i+3]
                buf[i+3] = int((r + g + b) / 3)
        return bytes(buf)
Exemple #8
0
    def cubemap_to_equirectangular(self, imageList, outputName):

        # Define the vertex shader
        vertex_shader = '''
            in vec3 aVertexPosition;
            in vec2 aVertexTextureCoord;

            out vec2 vTexCoord;

            void main() {
                vTexCoord = aVertexTextureCoord;
                gl_Position = vec4(aVertexPosition, 1);
            }
        '''

        # Generate the OpenGL shader
        pos = [
            (-1.0, -1.0, -1.0),  # left,  bottom, back
            (-1.0, 1.0, -1.0),  # left,  top,    back
            (1.0, -1.0, -1.0),  # right, bottom, back
            (1.0, 1.0, -1.0)
        ]  # right, top,    back
        coords = [
            (-1.0, -1.0),  # left,  bottom
            (-1.0, 1.0),  # left,  top
            (1.0, -1.0),  # right, bottom
            (1.0, 1.0)
        ]  # right, top
        vertexIndices = [(0, 3, 1), (3, 0, 2)]
        shader = gpu.types.GPUShader(vertex_shader, self.frag_shader)

        batch = batch_for_shader(shader, 'TRIS', {"aVertexPosition": pos,\
                                                  "aVertexTextureCoord": coords},\
                                                  indices=vertexIndices)

        # Change the color space of all of the images to Linear
        # and load them into OpenGL textures
        for image in imageList:
            image.colorspace_settings.name = 'Linear'
            image.gl_load()

        # set the size of the final image
        width = self.image_size[0]
        height = self.image_size[1]

        # Create an offscreen render buffer and texture
        offscreen = gpu.types.GPUOffScreen(width, height)

        with offscreen.bind():
            bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)

            shader.bind()

            def bind_and_filter(tex, bindcode, image=None, imageNum=None):
                bgl.glActiveTexture(tex)
                bgl.glBindTexture(bgl.GL_TEXTURE_2D, bindcode)
                bgl.glTexParameterf(bgl.GL_TEXTURE_2D,
                                    bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR)
                bgl.glTexParameterf(bgl.GL_TEXTURE_2D,
                                    bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR)
                bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                                    bgl.GL_CLAMP_TO_EDGE)
                bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                                    bgl.GL_CLAMP_TO_EDGE)
                if image != None and imageNum != None:
                    shader.uniform_int(image, imageNum)

            # Bind all of the cubemap textures and enable correct filtering and wrapping
            # to prevent seams
            bind_and_filter(bgl.GL_TEXTURE0, imageList[0].bindcode,
                            "cubeLeftImage", 0)
            bind_and_filter(bgl.GL_TEXTURE1, imageList[1].bindcode,
                            "cubeRightImage", 1)
            bind_and_filter(bgl.GL_TEXTURE2, imageList[2].bindcode,
                            "cubeBottomImage", 2)
            bind_and_filter(bgl.GL_TEXTURE3, imageList[3].bindcode,
                            "cubeTopImage", 3)
            bind_and_filter(bgl.GL_TEXTURE4, imageList[4].bindcode,
                            "cubeFrontImage", 4)
            if not self.no_back_image:
                bind_and_filter(bgl.GL_TEXTURE5, imageList[5].bindcode,
                                "cubeBackImage", 5)

            # Bind the resulting texture
            bind_and_filter(bgl.GL_TEXTURE6, offscreen.color_texture)

            # Render the image
            batch.draw(shader)

            # Unload the textures
            for image in imageList:
                image.gl_free()

            # Read the resulting pixels into a buffer
            buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4)
            bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, bgl.GL_FLOAT,
                              buffer)

        # Unload the offscreen texture
        offscreen.free()

        # Remove the cubemap textures:
        for image in imageList:
            bpy.data.images.remove(image)

        # Copy the pixels from the buffer to an image object
        if not outputName in bpy.data.images.keys():
            bpy.data.images.new(outputName, width, height)
        imageRes = bpy.data.images[outputName]
        imageRes.scale(width, height)
        imageRes.pixels = buffer
        return imageRes
Exemple #9
0
def read_tex(reader, printer):
    import bgl
    global name_format
    r = reader
    p = printer

    p("tex file version: {}", r.i32())
    num_textures = p("num textures: {}", r.i32())

    already_seen = set()

    for i in range(num_textures):
        p("texture #{}", i)
        checksum = p("  checksum: {}", to_hex_string(r.u32()))

        if checksum in already_seen:
            p("Duplicate checksum!", None)
        else:
            already_seen.add(checksum)

        create_image = (checksum not in bpy.data.images)
        if not create_image:
            p("Image {} already exists, will not be created!", checksum)

        # tex_map[checksum] = i

        img_width = p("  width: {}", r.u32())
        img_height = p("  height: {}", r.u32())
        levels = p("  levels: {}", r.u32())
        texel_depth = p("  texel depth: {}", r.u32())
        pal_depth = p("  palette depth: {}", r.u32())
        dxt_version = p("  dxt version: {}", r.u32())
        pal_size = p("  palette depth: {}", r.u32())

        if dxt_version == 2:
            dxt_version = 1

        if pal_size > 0:
            if pal_depth == 32:
                pal_colors = []
                for j in range(pal_size // 4):
                    cb, cg, cr, ca = r.read("4B")
                    pal_colors.append(
                        (cr / 255.0, cb / 255.0, cb / 255.0, ca / 255.0))
            else:
                r.read(str(pal_size) + "B")

        for j in range(levels):
            data_size = r.u32()

            if not create_image:
                r.offset += data_size
                continue

            if j == 0 and dxt_version == 0:
                data_bytes = r.buf[r.offset:r.offset + data_size]
                if pal_size > 0 and pal_depth == 32 and texel_depth == 8:
                    data_bytes = swizzle(data_bytes, img_width, img_height, 8,
                                         0, True)
                    blend_img = bpy.data.images.new(str(checksum),
                                                    img_width,
                                                    img_height,
                                                    alpha=True)
                    blend_img.pixels = [
                        pal_col for pal_idx in data_bytes
                        for pal_col in pal_colors[pal_idx]
                    ]
            elif j == 0 and dxt_version in (1, 5):
                data_bytes = r.buf[r.offset:r.offset + data_size]
                blend_img = bpy.data.images.new(str(checksum),
                                                img_width,
                                                img_height,
                                                alpha=True)
                blend_img.gl_load()
                blend_img.thug_image_props.compression_type = "DXT5" if dxt_version == 5 else "DXT1"
                image_id = blend_img.bindcode[0]
                if image_id == 0:
                    print("Got 0 bindcode for " + blend_img.name)
                else:
                    buf = bgl.Buffer(bgl.GL_BYTE, len(data_bytes))
                    buf[:] = data_bytes
                    bgl.glBindTexture(bgl.GL_TEXTURE_2D, image_id)
                    bgl.glCompressedTexImage2D(
                        bgl.GL_TEXTURE_2D,
                        0,
                        COMPRESSED_RGBA_S3TC_DXT5_EXT
                        if dxt_version == 5 else COMPRESSED_RGBA_S3TC_DXT1_EXT,
                        img_width,  #level_img_width,
                        img_height,  #level_img_height,
                        0,
                        len(data_bytes),
                        buf)
                    del buf

                    buf_size = img_width * img_height * 4
                    # LOG.debug(buf_size)
                    buf = bgl.Buffer(bgl.GL_FLOAT, buf_size)
                    bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA,
                                      bgl.GL_FLOAT, buf)
                    blend_img.pixels = buf
                    blend_img.pack(as_png=True)
                    del buf

            r.offset += data_size
Exemple #10
0
def get_texture(name):
    """nameが'icons'なら全体のテクスチャを返す
    :type name: str
    """
    if name in textures:
        return textures[name]

    if name in internal_icons:
        textures[name] = internal_icons[name]
        return textures[name]

    if name == 'icons':
        icon_type = 'icons'
    elif name in icons and icons[name] < 780:  # 780は'BRUSH_ADD':
        icon_type = 'icon'
    elif name in brush_icons:
        icon_type = 'brush'
    elif name in matcap_icons:
        icon_type = 'matcap'
    elif '.' in name:
        icon_type = 'image'
    else:
        return None

    dirname = os.path.dirname(os.path.abspath(__file__))

    if name == 'icons':
        filepath = os.path.join(dirname, ICON_FILE_NAME)
        img = load_image(filepath)
        if not img:
            return None
        sx, sy = img.size
        buf = bgl.Buffer(bgl.GL_FLOAT, 4 * sx * sy)
        img.gl_load(filter=bgl.GL_LINEAR, mag=bgl.GL_LINEAR)
        # TODO: 仕様変更があったので動作確認 -> img.bindcode
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, img.bindcode[0])
        bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0,
                          bgl.GL_RGBA, bgl.GL_FLOAT, buf)
        img.gl_free()
        img.user_clear()
        bpy.data.images.remove(img)
        x = y = 0
        w = sx
        h = sy

    elif icon_type == 'icon':
        if 'icons' not in textures:
            get_texture('icons')
        tex, buf, sx, sy, _x, _y, _w, _h = textures['icons']
        row, col = divmod(icons[name], 26)
        x = 10 + (40 + 2) * col
        y = 10 + (40 + 2) * row
        w = h = 32

    elif icon_type in ('brush', 'matcap'):
        if icon_type == 'brush':
            filepath = os.path.join(dirname, 'brushicons', brush_icons[name])
        else:
            filepath = os.path.join(dirname, 'matcaps', matcap_icons[name])
        buf, sx, sy = get_image_buffer(filepath)
        if not buf:
            return None
        x = y = 0
        w, h = sx, sy
    else:
        buf, sx, sy = get_image_buffer(name)
        if not buf:
            return None
        x = y = 0
        w, h = sx, sy

    if icon_type == 'icon':
        textures[name] = [tex, buf, sx, sy, x, y, w, h]
    else:
        texture = bgl.Buffer(bgl.GL_INT, 1)  # GLuint
        bgl.glGenTextures(1, texture)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture[0])
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER,
                            bgl.GL_LINEAR)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER,
                            bgl.GL_LINEAR)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP)
        bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA,
                         sx, sy, 0, bgl.GL_RGBA, bgl.GL_FLOAT, buf)
        textures[name] = [texture[0], buf, sx, sy, x, y, w, h]
    return textures[name]
Exemple #11
0
    def cubemap_to_equirectangular(self, imageList, outputName):

        # Define the vertex shader
        vertex_shader = '''
            in vec3 aVertexPosition;
            in vec2 aVertexTextureCoord;

            out vec2 vTexCoord;

            void main() {
                vTexCoord = aVertexTextureCoord;
                gl_Position = vec4(aVertexPosition, 1);
            }
        '''

        # Define the fragment shader for the 360 degree conversion
        fragment_shader_360 = '''
            #define PI 3.1415926535897932384626
            
            // Input cubemap textures
            uniform sampler2D cubeLeftImage;
            uniform sampler2D cubeRightImage;
            uniform sampler2D cubeBottomImage;
            uniform sampler2D cubeTopImage;
            uniform sampler2D cubeBackImage;
            uniform sampler2D cubeFrontImage;

            in vec2 vTexCoord;

            out vec4 fragColor;

            void main() {
            
                // Calculate the pointing angle
                float azimuth = vTexCoord.x * PI;
                float elevation = vTexCoord.y * PI / 2.0;
                
                // Calculate the pointing vector
                vec3 pt;
                pt.x = cos(elevation) * sin(azimuth);
                pt.y = sin(elevation);
                pt.z = cos(elevation) * cos(azimuth);
                
                // Select the correct pixel
                if ((abs(pt.x) >= abs(pt.y)) && (abs(pt.x) >= abs(pt.z))) {
                    if (pt.x <= 0.0) {
                        fragColor = texture(cubeLeftImage, vec2(((-pt.z/pt.x)+1.0)/2.0,((-pt.y/pt.x)+1.0)/2.0));
                    } else {
                        fragColor = texture(cubeRightImage, vec2(((-pt.z/pt.x)+1.0)/2.0,((pt.y/pt.x)+1.0)/2.0));
                    }
                } else if (abs(pt.y) >= abs(pt.z)) {
                    if (pt.y <= 0.0) {
                        fragColor = texture(cubeBottomImage, vec2(((-pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+1.0)/2.0));
                    } else {
                        fragColor = texture(cubeTopImage, vec2(((pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+1.0)/2.0));
                    }
                } else {
                    if (pt.z <= 0.0) {
                        fragColor = texture(cubeBackImage, vec2(((pt.x/pt.z)+1.0)/2.0,((-pt.y/pt.z)+1.0)/2.0));
                    } else {
                        fragColor = texture(cubeFrontImage, vec2(((pt.x/pt.z)+1.0)/2.0,((pt.y/pt.z)+1.0)/2.0));
                    }
                }
            }
        '''

        # Define the fragment shader for the 180 degree conversion
        fragment_shader_180 = '''
            #define PI 3.1415926535897932384626
            
            // Input cubemap textures
            uniform sampler2D cubeLeftImage;
            uniform sampler2D cubeRightImage;
            uniform sampler2D cubeBottomImage;
            uniform sampler2D cubeTopImage;
            uniform sampler2D cubeFrontImage;

            in vec2 vTexCoord;

            out vec4 fragColor;

            void main() {{
            
                // Calculate the pointing angle
                float fovd = {0};
                float fovfrac = fovd/360.0;
                float sidefrac = (fovd-90.0)/180;
                float azimuth = vTexCoord.x * PI * fovfrac;
                float elevation = vTexCoord.y * PI / 2.0;
                
                // Calculate the pointing vector
                vec3 pt;
                pt.x = cos(elevation) * sin(azimuth);
                pt.y = sin(elevation);
                pt.z = cos(elevation) * cos(azimuth);
                
                // Select the correct pixel
                if ((abs(pt.x) >= abs(pt.y)) && (abs(pt.x) >= abs(pt.z))) {{
                    if (pt.x <= 0.0) {{
                        fragColor = texture(cubeLeftImage, vec2((((-pt.z/pt.x))+(2.0*sidefrac-1.0))/(2.0*sidefrac),((-pt.y/pt.x)+1.0)/2.0));
                    }} else {{
                        fragColor = texture(cubeRightImage, vec2(((-pt.z/pt.x)+1.0)/(2.0*sidefrac),((pt.y/pt.x)+1.0)/2.0));
                    }}
                }} else if (abs(pt.y) >= abs(pt.z)) {{
                    if (pt.y <= 0.0) {{
                        fragColor = texture(cubeBottomImage, vec2(((-pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+(2.0*sidefrac-1.0))/(2.0*sidefrac)));
                    }} else {{
                        fragColor = texture(cubeTopImage, vec2(((pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+1.0)/(2.0*sidefrac)));
                    }}
                }} else {{
                    fragColor = texture(cubeFrontImage, vec2(((pt.x/pt.z)+1.0)/2.0,((pt.y/pt.z)+1.0)/2.0));
                }}
            }}
        '''.format(self.FOV)

        # Define the fragment shader for the dome conversion
        fragment_shader_dome = '''
            #define PI 3.1415926535897932384626
            
            // Input cubemap textures
            uniform sampler2D cubeLeftImage;
            uniform sampler2D cubeRightImage;
            uniform sampler2D cubeBottomImage;
            uniform sampler2D cubeTopImage;
            uniform sampler2D cubeFrontImage;
            uniform sampler2D cubeBackImage;

            in vec2 vTexCoord;

            out vec4 fragColor;

            void main() {{

                float fovd = {0};
                float fovfrac = fovd/360.0;
                float sidefrac = (fovd-90.0)/180;
                float hfov = fovfrac*PI;
                vec2 d = vTexCoord.xy;

                float r = length( d );
                if( r > 1.0 ) {{
                    fragColor = vec4(0.0, 0.0, 0.0, 1.0);
                    return;
                }}
                
                vec2 dunit = normalize( d );
                float phi = r * hfov;
                vec3 pt = vec3( 1.0, 1.0, 1.0 );
                pt.xy = dunit * sin( phi );
                pt.z = cos( phi );  // Select the correct pixel
                
                // Select the correct pixel
                if ((abs(pt.x) >= abs(pt.y)) && (abs(pt.x) >= abs(pt.z))) {{
                    if (pt.x <= 0.0) {{
                        fragColor = texture(cubeLeftImage, vec2((((-pt.z/pt.x))+(2.0*sidefrac-1.0))/(2.0*sidefrac),((-pt.y/pt.x)+1.0)/2.0));
                    }} else {{
                        fragColor = texture(cubeRightImage, vec2(((-pt.z/pt.x)+1.0)/(2.0*sidefrac),((pt.y/pt.x)+1.0)/2.0));
                    }}
                }} else if (abs(pt.y) >= abs(pt.z)) {{
                    if (pt.y <= 0.0) {{
                        fragColor = texture(cubeBottomImage, vec2(((-pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+(2.0*sidefrac-1.0))/(2.0*sidefrac)));
                    }} else {{
                        fragColor = texture(cubeTopImage, vec2(((pt.x/pt.y)+1.0)/2.0,((-pt.z/pt.y)+1.0)/(2.0*sidefrac)));
                    }}
                }} else {{
                    if (pt.z <= 0.0) {{
                        fragColor = texture(cubeBackImage, vec2(((pt.x/pt.z)+1.0)/2.0,((-pt.y/pt.z)+1.0)/2.0));
                    }} else {{
                        fragColor = texture(cubeFrontImage, vec2(((pt.x/pt.z)+1.0)/2.0,((pt.y/pt.z)+1.0)/2.0));
                    }}
                }}
            }}
        '''.format(self.FOV)

        # Generate the OpenGL shader
        pos = [
            (-1.0, -1.0, -1.0),  # left,  bottom, back
            (-1.0, 1.0, -1.0),  # left,  top,    back
            (1.0, -1.0, -1.0),  # right, bottom, back
            (1.0, 1.0, -1.0)
        ]  # right, top,    back
        coords = [
            (-1.0, -1.0),  # left,  bottom
            (-1.0, 1.0),  # left,  top
            (1.0, -1.0),  # right, bottom
            (1.0, 1.0)
        ]  # right, top
        vertexIndices = [(0, 3, 1), (3, 0, 2)]
        if self.is_dome:
            shader = gpu.types.GPUShader(vertex_shader, fragment_shader_dome)
        else:
            if self.no_back_image:
                shader = gpu.types.GPUShader(vertex_shader,
                                             fragment_shader_180)
            else:
                shader = gpu.types.GPUShader(vertex_shader,
                                             fragment_shader_360)
        batch = batch_for_shader(shader, 'TRIS', {"aVertexPosition": pos,\
                                                  "aVertexTextureCoord": coords},\
                                                  indices=vertexIndices)

        # Change the color space of all of the images to Linear
        # and load them into OpenGL textures
        imageLeft = imageList[0]
        imageLeft.colorspace_settings.name = 'Linear'
        imageLeft.gl_load()

        imageRight = imageList[1]
        imageRight.colorspace_settings.name = 'Linear'
        imageRight.gl_load()

        imageBottom = imageList[2]
        imageBottom.colorspace_settings.name = 'Linear'
        imageBottom.gl_load()

        imageTop = imageList[3]
        imageTop.colorspace_settings.name = 'Linear'
        imageTop.gl_load()

        imageFront = imageList[4]
        imageFront.colorspace_settings.name = 'Linear'
        imageFront.gl_load()

        if not self.no_back_image:
            imageBack = imageList[5]
            imageBack.colorspace_settings.name = 'Linear'
            imageBack.gl_load()

        # set the size of the final image
        width = self.image_size[0]
        height = self.image_size[1]

        # Create an offscreen render buffer and texture
        offscreen = gpu.types.GPUOffScreen(width, height)

        with offscreen.bind():
            bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)

            shader.bind()

            # Bind all of the cubemap textures and enable correct filtering and wrapping
            # to prevent seams
            bgl.glActiveTexture(bgl.GL_TEXTURE0)
            bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageLeft.bindcode)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                                bgl.GL_CLAMP_TO_EDGE)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                                bgl.GL_CLAMP_TO_EDGE)
            shader.uniform_int("cubeLeftImage", 0)

            bgl.glActiveTexture(bgl.GL_TEXTURE1)
            bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageRight.bindcode)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                                bgl.GL_CLAMP_TO_EDGE)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                                bgl.GL_CLAMP_TO_EDGE)
            shader.uniform_int("cubeRightImage", 1)

            bgl.glActiveTexture(bgl.GL_TEXTURE2)
            bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageBottom.bindcode)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                                bgl.GL_CLAMP_TO_EDGE)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                                bgl.GL_CLAMP_TO_EDGE)
            shader.uniform_int("cubeBottomImage", 2)

            bgl.glActiveTexture(bgl.GL_TEXTURE3)
            bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageTop.bindcode)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                                bgl.GL_CLAMP_TO_EDGE)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                                bgl.GL_CLAMP_TO_EDGE)
            shader.uniform_int("cubeTopImage", 3)

            bgl.glActiveTexture(bgl.GL_TEXTURE4)
            bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageFront.bindcode)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                                bgl.GL_CLAMP_TO_EDGE)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                                bgl.GL_CLAMP_TO_EDGE)
            shader.uniform_int("cubeFrontImage", 4)

            if not self.no_back_image:
                bgl.glActiveTexture(bgl.GL_TEXTURE5)
                bgl.glBindTexture(bgl.GL_TEXTURE_2D, imageBack.bindcode)
                bgl.glTexParameterf(bgl.GL_TEXTURE_2D,
                                    bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR)
                bgl.glTexParameterf(bgl.GL_TEXTURE_2D,
                                    bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR)
                bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                                    bgl.GL_CLAMP_TO_EDGE)
                bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                                    bgl.GL_CLAMP_TO_EDGE)
                shader.uniform_int("cubeBackImage", 5)

            # Bind the resulting texture
            bgl.glActiveTexture(bgl.GL_TEXTURE6)
            bgl.glBindTexture(bgl.GL_TEXTURE_2D, offscreen.color_texture)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameterf(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER,
                                bgl.GL_LINEAR)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                                bgl.GL_CLAMP_TO_EDGE)
            bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                                bgl.GL_CLAMP_TO_EDGE)

            # Render the image
            batch.draw(shader)

            # Unload the textures
            imageLeft.gl_free()
            imageRight.gl_free()
            imageBottom.gl_free()
            imageTop.gl_free()
            imageFront.gl_free()
            if not self.no_back_image:
                imageBack.gl_free()

            # Read the resulting pixels into a buffer
            buffer = bgl.Buffer(bgl.GL_FLOAT, width * height * 4)
            bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, bgl.GL_FLOAT,
                              buffer)

        # Unload the offscreen texture
        offscreen.free()

        # Remove the cubemap textures:
        for image in imageList:
            bpy.data.images.remove(image)

        # Copy the pixels from the buffer to an image object
        if not outputName in bpy.data.images.keys():
            bpy.data.images.new(outputName, width, height)
        imageRes = bpy.data.images[outputName]
        imageRes.scale(width, height)
        imageRes.pixels = buffer
        return imageRes
Exemple #12
0
    def render_image(self):

        # Render the scene and load it into the script
        tmp_path = self.scene.render.filepath
        tmp_image = 'temp_img_store' + '.png'
        if tmp_image in bpy.data.images:
            bpy.data.images.remove(bpy.data.images[tmp_image])
        self.scene.render.filepath = self.path + tmp_image
        bpy.ops.render.render(write_still=True)
        renderedImage = bpy.data.images.load(self.path + tmp_image)
        renderedImage.colorspace_settings.name = 'Linear'

        # Vertex shader for cubemap frontimage to equirectangular
        vertex_shader = '''
            in vec3 aVertexPosition;
            in vec2 aVertexTextureCoord;
        
            out vec2 vTexCoord;
        
            void main() {
                vTexCoord = aVertexTextureCoord;
                gl_Position = vec4(aVertexPosition, 1);
            }
        '''

        # Generate the OpenGL shader
        pos = [(-1.0, -1.0, -1.0), (-1.0,  1.0, -1.0), \
               (1.0, -1.0, -1.0), (1.0,  1.0, -1.0)]
        coords = [(-2.0, -1.0), (-2.0,  1.0), \
                  (2.0, -1.0), (2.0,  1.0)]
        vertexIndices = [(0, 3, 1), (3, 0, 2)]

        shader = gpu.types.GPUShader(vertex_shader, self.frag_shader)
        batch = batch_for_shader(shader, 'TRIS', {"aVertexPosition": pos, \
                                                  "aVertexTextureCoord": coords}, \
                                                  indices=vertexIndices)

        # Load rendered image into OpenGL textures
        renderedImage.gl_load()

        # Create an offscreen render buffer and texture
        offscreen = gpu.types.GPUOffScreen(self.image_size[0],
                                           self.image_size[1])

        with offscreen.bind():
            #bgl.glClearColor(0,0,0,1)
            bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)

            shader.bind()

            def bind_and_filter(tex, bindcode, image=None, imageNum=None):
                bgl.glActiveTexture(tex)
                bgl.glBindTexture(bgl.GL_TEXTURE_2D, bindcode)
                bgl.glTexParameterf(bgl.GL_TEXTURE_2D,
                                    bgl.GL_TEXTURE_MIN_FILTER, bgl.GL_LINEAR)
                bgl.glTexParameterf(bgl.GL_TEXTURE_2D,
                                    bgl.GL_TEXTURE_MAG_FILTER, bgl.GL_LINEAR)
                # Turn on GL_CLAMP_TO_BORDER and delete paint black codes in fragment shader
                # would give a transparent background
                #bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S, bgl.GL_CLAMP_TO_BORDER)
                #bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T, bgl.GL_CLAMP_TO_BORDER)
                # Really dont know how to change the border color
                #bgl.glTexParameterfv(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_BORDER_COLOR, color)#???
                if image != None and imageNum != None:
                    shader.uniform_int(image, imageNum)

            # Bind and filter the renderedImage
            bind_and_filter(bgl.GL_TEXTURE0, renderedImage.bindcode,
                            "frontImage", 0)

            # Bind the resulting texture
            bind_and_filter(bgl.GL_TEXTURE1, offscreen.color_texture)

            # Render the image
            batch.draw(shader)

            # Unload the texture
            renderedImage.gl_free()

            # Read the resulting pixels into a buffer
            buffer = bgl.Buffer(bgl.GL_FLOAT,
                                self.image_size[0] * self.image_size[1] * 4)
            bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, bgl.GL_FLOAT,
                              buffer)

        # Unload the offscreen texture
        offscreen.free()

        # Remove the frontImage texture
        bpy.data.images.remove(renderedImage)
        # Turn on this line to delete tmp image everytime, turn off maybe will save some resource
        #os.remove(self.path + tmp_image)

        # Set file name
        image_name = "frameS{:06d}.png".format(self.scene.frame_current)
        # If it doesn't already exist, create an image object to store the resulting render
        if not image_name in bpy.data.images.keys():
            imageResult = bpy.data.images.new(image_name, self.image_size[0],
                                              self.image_size[1])
        imageResult = bpy.data.images[image_name]
        imageResult.scale(self.image_size[0], self.image_size[1])

        # Copy the pixels from the buffer to an image object
        imageResult.pixels = buffer

        # Save to file
        imageResult.file_format = 'PNG'
        imageResult.filepath_raw = self.path + image_name
        imageResult.save()

        bpy.data.images.remove(imageResult)

        self.scene.render.filepath = tmp_path
Exemple #13
0
def get_texture(name):
    """nameが'icons'なら全体のテクスチャを返す
    :type name: str
    """
    if name in textures:
        return textures[name]

    if name in internal_icons:
        textures[name] = internal_icons[name]
        return textures[name]

    if name == 'icons':
        icon_type = 'icons'
    elif name in icons and icons[name] < 780:  # 780は'BRUSH_ADD':
        icon_type = 'icon'
    elif name in brush_icons:
        icon_type = 'brush'
    elif name in matcap_icons:
        icon_type = 'matcap'
    elif '.' in name:
        icon_type = 'image'
    else:
        return None

    dirname = os.path.dirname(os.path.abspath(__file__))

    if name == 'icons':
        filepath = os.path.join(dirname, ICON_FILE_NAME)
        img = load_image(filepath)
        if not img:
            return None
        sx, sy = img.size
        buf = bgl.Buffer(bgl.GL_FLOAT, 4 * sx * sy)
        img.gl_load(filter=bgl.GL_LINEAR, mag=bgl.GL_LINEAR)
        # TODO: 仕様変更があったので動作確認 -> img.bindcode
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, img.bindcode[0])
        bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, bgl.GL_FLOAT, buf)
        img.gl_free()
        img.user_clear()
        bpy.data.images.remove(img)
        x = y = 0
        w = sx
        h = sy

    elif icon_type == 'icon':
        if 'icons' not in textures:
            get_texture('icons')
        tex, buf, sx, sy, _x, _y, _w, _h = textures['icons']
        row, col = divmod(icons[name], 26)
        x = 10 + (40 + 2) * col
        y = 10 + (40 + 2) * row
        w = h = 32

    elif icon_type in ('brush', 'matcap'):
        if icon_type == 'brush':
            filepath = os.path.join(dirname, 'brushicons', brush_icons[name])
        else:
            filepath = os.path.join(dirname, 'matcaps', matcap_icons[name])
        buf, sx, sy = get_image_buffer(filepath)
        if not buf:
            return None
        x = y = 0
        w, h = sx, sy
    else:
        buf, sx, sy = get_image_buffer(name)
        if not buf:
            return None
        x = y = 0
        w, h = sx, sy

    if icon_type == 'icon':
        textures[name] = [tex, buf, sx, sy, x, y, w, h]
    else:
        texture = bgl.Buffer(bgl.GL_INT, 1)  # GLuint
        bgl.glGenTextures(1, texture)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture[0])
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER,
                            bgl.GL_LINEAR)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER,
                            bgl.GL_LINEAR)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                            bgl.GL_CLAMP)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                            bgl.GL_CLAMP)
        bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, sx, sy, 0,
                         bgl.GL_RGBA, bgl.GL_FLOAT, buf)
        textures[name] = [texture[0], buf, sx, sy, x, y, w, h]
    return textures[name]
Exemple #14
0
def get_texture(name):
    """nameが"icons"なら全体のテクスチャを返す
    :type name: str
    """
    if name in textures:
        return textures[name]

    if name in internal_icons:
        textures[name] = internal_icons[name]
        return textures[name]

    if name == "icons":
        icon_type = "icons"
    elif name in icons and icons[name] < 780:  # 780は"BRUSH_ADD":
        icon_type = "icon"
    elif name in brush_icons:
        icon_type = "brush"
    elif name in matcap_icons:
        icon_type = "matcap"
    elif "." in name:  # 拡張子のドット
        icon_type = "image"
    else:
        return None

    dirname = os.path.dirname(os.path.abspath(__file__))

    if name == "icons":
        filepath = os.path.join(dirname, ICON_FILE_NAME)
        img = load_image(filepath)
        if not img:
            return None
        sx, sy = img.size
        buf = bgl.Buffer(bgl.GL_FLOAT, 4 * sx * sy)
        img.gl_load(filter=bgl.GL_LINEAR, mag=bgl.GL_LINEAR)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, img.bindcode[0])
        bgl.glGetTexImage(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, bgl.GL_FLOAT, buf)
        img.gl_free()
        img.user_clear()
        bpy.data.images.remove(img)
        x = y = 0
        w = sx
        h = sy

    elif icon_type == "icon":
        if "icons" not in textures:
            get_texture("icons")
        tex, buf, sx, sy, _x, _y, _w, _h = textures["icons"]
        row, col = divmod(icons[name], 26)
        x = 10 + (40 + 2) * col
        y = 10 + (40 + 2) * row
        w = h = 32

    elif icon_type in ("brush", "matcap"):
        if icon_type == "brush":
            filepath = os.path.join(dirname, "brushicons", brush_icons[name])
        else:
            filepath = os.path.join(dirname, "matcaps", matcap_icons[name])
        buf, sx, sy = get_image_buffer(filepath)
        if not buf:
            return None
        x = y = 0
        w, h = sx, sy
    else:
        buf, sx, sy = get_image_buffer(name)
        if not buf:
            return None
        x = y = 0
        w, h = sx, sy

    if icon_type == "icon":
        textures[name] = [tex, buf, sx, sy, x, y, w, h]
    else:
        texture = bgl.Buffer(bgl.GL_INT, 1)  # GLuint
        bgl.glGenTextures(1, texture)
        bgl.glBindTexture(bgl.GL_TEXTURE_2D, texture[0])
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MAG_FILTER,
                            bgl.GL_LINEAR)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_MIN_FILTER,
                            bgl.GL_LINEAR)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_S,
                            bgl.GL_CLAMP)
        bgl.glTexParameteri(bgl.GL_TEXTURE_2D, bgl.GL_TEXTURE_WRAP_T,
                            bgl.GL_CLAMP)
        bgl.glTexImage2D(bgl.GL_TEXTURE_2D, 0, bgl.GL_RGBA, sx, sy, 0,
                         bgl.GL_RGBA, bgl.GL_FLOAT, buf)
        textures[name] = [texture[0], buf, sx, sy, x, y, w, h]
    return textures[name]