CSharpGL(29)初步封装Texture和Framebuffer

+BIT祝威+悄悄在此留下版了个权的信息说:

CSharpGL(29)初步封装Texture和Framebuffer

+BIT祝威+悄悄在此留下版了个权的信息说:

Texture和Framebuffer

Texture和Framebuffer是OpenGL进行3D渲染高级效果必不可少的利器。有了Texture和Framebuffer就可以实现体渲染(Volume Rendering)等效果。现在到了对Texture和Framebuffer的创建、修改、使用进行封装的时候。

+BIT祝威+悄悄在此留下版了个权的信息说:

下载

CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入(https://github.com/bitzhuwei/CSharpGL

+BIT祝威+悄悄在此留下版了个权的信息说:

封装Texture

过程式的Texture

首先观察一下平时是如何创建和使用Texture对象的。

+BIT祝威+悄悄在此留下版了个权的信息说:

创建Texture

以创建2D Texture为例。

 1 uint CreateTexture(Bitmap bitmap)
 2 {
 3     glActiveTexture(OpenGL.GL_TEXTURE0);
 4     var id = new uint[1];
 5     OpenGL.GenTextures(1, id);
 6     OpenGL.BindTexture(target, id[0]);
 7     OpenGL.TexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_R, (int)OpenGL.GL_CLAMP_TO_EDGE);
 8     OpenGL.TexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_S, (int)OpenGL.GL_CLAMP_TO_EDGE);
 9     OpenGL.TexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_WRAP_T, (int)OpenGL.GL_CLAMP_TO_EDGE);
10     OpenGL.TexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MIN_FILTER, (int)OpenGL.GL_REPEAT);
11     OpenGL.TexParameteri(OpenGL.GL_TEXTURE_2D, OpenGL.GL_TEXTURE_MAG_FILTER, (int)OpenGL.GL_REPEAT);
12
13     BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
14         ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
15     OpenGL.TexImage2D(OpenGL.GL_TEXTURE_2D, 0, OpenGL.GL_RGBA, bitmap.Width, bitmap.Height, 0, OpenGL.GL_BGRA, OpenGL.GL_UNSIGNED_BYTE, bitmapData.Scan0);
16     bitmap.UnlockBits(bitmapData);
17
18     return id[0];
19 }

CreateTexture

使用Texture

使用上述Texture的方式:

 1 void UseTexture(string textureNameInShader, uint textureId)
 2 {
 3     uint target = OpenGL.GL_TEXTURE0;
 4     glActiveTexture(target);
 5     OpenGL.BindTexture(OpenGL.GL_TEXTURE_2D, textureId);
 6     SetUniform("textureNameInShader", target - OpenGL.GL_TEXTURE0);
 7 }
 8
 9 int SetUniform(string uniformName, uint v0)
10 {
11     int location = GetUniformLocation(uniformName);
12     if (location >= 0)
13     {
14         glUniform1ui(GetUniformLocation(uniformName), v0);
15     }
16     return location;
17 }

封装的Texture

从上述创建Texture的过程可知,创建Texture主要有2个步骤:设置Sampler和填充Texture数据。Sampler就是各个滤波选项。填充数据就是用glTexImage2D()一类的命令指定Texture的内容。

 1 void Initialize()
 2 {
 3     glActiveTexture(this.ActiveTexture);
 4     OpenGL.GenTextures(1, id);
 5     BindTextureTarget target = this.Target;
 6     OpenGL.BindTexture(target, id[0]);
 7     this.Sampler.Bind(this.ActiveTexture - OpenGL.GL_TEXTURE0, target);
 8     this.ImageFiller.Fill(target);
 9     OpenGL.GenerateMipmap((MipmapTarget)((uint)target));// TODO: does this work?
10     //this.SamplerBuilder.Unbind(OpenGL.GL_TEXTURE0 - OpenGL.GL_TEXTURE0, this.Target);
11     OpenGL.BindTexture(this.Target, 0);
12 }

+BIT祝威+悄悄在此留下版了个权的信息说:

Sampler

Sampler中主要就是那几个滤波选项。

 1     /// <summary>
 2     /// texture‘s settings.
 3     /// </summary>
 4     public class SamplerParameters
 5     {
 6         public TextureWrapping wrapS = TextureWrapping.ClampToEdge;
 7         public TextureWrapping wrapT = TextureWrapping.ClampToEdge;
 8         public TextureWrapping wrapR = TextureWrapping.ClampToEdge;
 9         public TextureFilter minFilter = TextureFilter.Linear;
10         public TextureFilter magFilter = TextureFilter.Linear;
11
12         public SamplerParameters() { }
13     }

+BIT祝威+悄悄在此留下版了个权的信息说:

Sampler的唯一任务就是在创建Texture时指定某些滤波。

 1     /// <summary>
 2     /// texture‘s settings.
 3     /// </summary>
 4     public abstract class SamplerBase
 5     {
 6         protected MipmapFilter mipmapFilter;
 7         public SamplerParameters Parameters { get; protected set; }
 8
 9         /// <summary>
10         /// texture‘s settings.
11         /// </summary>
12         /// <param name="parameters"></param>
13         /// <param name="mipmapFilter"></param>
14         public SamplerBase(SamplerParameters parameters, MipmapFilter mipmapFilter)
15         {
16             if (parameters == null)
17             {
18                 this.Parameters = new SamplerParameters();
19             }
20             else
21             {
22                 this.Parameters = parameters;
23             }
24
25             this.mipmapFilter = mipmapFilter;
26         }
27
28         /// <summary>
29         ///
30         /// </summary>
31         /// <param name="unit">OpenGL.GL_TEXTURE0 etc.</param>
32         /// <param name="target"></param>
33         public abstract void Bind(uint unit, BindTextureTarget target);
34
35     }

实际上为了简化指定Sampler的操作,OpenGL提供了一个Sampler对象。这里顺便也把它封装了。

 1     /// <summary>
 2     /// texture‘s settings.
 3     /// </summary>
 4     public partial class Sampler : SamplerBase, IDisposable
 5     {
 6         /// <summary>
 7         /// sampler‘s Id.
 8         /// </summary>
 9         public uint Id { get; private set; }
10
11         /// <summary>
12         /// texture‘s settings.
13         /// </summary>
14         /// <param name="parameters"></param>
15         /// <param name="mipmapFiltering"></param>
16         public Sampler(
17             SamplerParameters parameters = null,
18             MipmapFilter mipmapFiltering = MipmapFilter.LinearMipmapLinear)
19             : base(parameters, mipmapFiltering)
20         {
21
22         }
23
24         private bool initialized = false;
25         /// <summary>
26         ///
27         /// </summary>
28         public void Initialize(uint unit, BindTextureTarget target)
29         {
30             if (!this.initialized)
31             {
32                 this.DoInitialize(unit, target);
33                 this.initialized = true;
34             }
35         }
36
37         private void DoInitialize(uint unit, BindTextureTarget target)
38         {
39             var ids = new uint[1];
40             OpenGL.GenSamplers(1, ids);
41             this.Id = ids[0];
42             //OpenGL.BindSampler(unit, ids[0]);
43             OpenGL.BindSampler(unit, ids[0]);
44             /* Clamping to edges is important to prevent artifacts when scaling */
45             OpenGL.SamplerParameteri(ids[0], OpenGL.GL_TEXTURE_WRAP_R, (int)this.parameters.wrapR);
46             OpenGL.SamplerParameteri(ids[0], OpenGL.GL_TEXTURE_WRAP_S, (int)this.parameters.wrapS);
47             OpenGL.SamplerParameteri(ids[0], OpenGL.GL_TEXTURE_WRAP_T, (int)this.parameters.wrapT);
48             /* Linear filtering usually looks best for text */
49             OpenGL.SamplerParameteri(ids[0], OpenGL.GL_TEXTURE_MIN_FILTER, (int)this.parameters.minFilter);
50             OpenGL.SamplerParameteri(ids[0], OpenGL.GL_TEXTURE_MAG_FILTER, (int)this.parameters.magFilter);
51             // TODO: mipmap not used yet.
52
53             OpenGL.BindSampler(unit, 0);
54         }
55         /// <summary>
56         /// texture‘s settings.
57         /// </summary>
58         /// <param name="unit">OpenGL.GL_TEXTURE0 etc.</param>
59         /// <param name="target"></param>
60         public override void Bind(uint unit, BindTextureTarget target)
61         {
62             if (!this.initialized) { this.Initialize(unit, target); }
63
64             OpenGL.BindSampler(unit, this.Id);
65         }
66     }

Sampler

+BIT祝威+悄悄在此留下版了个权的信息说:

当然也可以不用这个OpenGL的Sampler对象,直接用glTexParameteri()等指令。这就像是一个假的Sampler对象在工作。

 1     /// <summary>
 2     /// texture‘s settings.
 3     /// </summary>
 4     public class FakeSampler : SamplerBase
 5     {
 6
 7         /// <summary>
 8         /// texture‘s settings.
 9         /// </summary>
10         /// <param name="parameters"></param>
11         /// <param name="mipmapFiltering"></param>
12         public FakeSampler(SamplerParameters parameters, MipmapFilter mipmapFiltering)
13             : base(parameters, mipmapFiltering)
14         {
15         }
16
17         /// <summary>
18         /// texture‘s settings.
19         /// </summary>
20         /// <param name="unit">OpenGL.GL_TEXTURE0 etc.</param>
21         /// <param name="target"></param>
22         public override void Bind(uint unit, BindTextureTarget target)
23         {
24             /* Clamping to edges is important to prevent artifacts when scaling */
25             OpenGL.TexParameteri((uint)target, OpenGL.GL_TEXTURE_WRAP_R, (int)this.parameters.wrapR);
26             OpenGL.TexParameteri((uint)target, OpenGL.GL_TEXTURE_WRAP_S, (int)this.parameters.wrapS);
27             OpenGL.TexParameteri((uint)target, OpenGL.GL_TEXTURE_WRAP_T, (int)this.parameters.wrapT);
28             /* Linear filtering usually looks best for text */
29             OpenGL.TexParameteri((uint)target, OpenGL.GL_TEXTURE_MIN_FILTER, (int)this.parameters.minFilter);
30             OpenGL.TexParameteri((uint)target, OpenGL.GL_TEXTURE_MAG_FILTER, (int)this.parameters.magFilter);
31             // TODO: mipmap filter not working yet.
32
33         }
34     }

FakeSampler

当然,有的时候根本不需要指定任何滤波选项。这可以用一个空的Sampler类型实现。

 1     /// <summary>
 2     /// do nothing about sampling in building texture.
 3     /// </summary>
 4     public class NullSampler : SamplerBase
 5     {
 6         /// <summary>
 7         /// do nothing about sampling in building texture.
 8         /// </summary>
 9         public NullSampler() : base(null, MipmapFilter.LinearMipmapLinear) { }
10
11         /// <summary>
12         /// do nothing.
13         /// </summary>
14         /// <param name="unit">OpenGL.GL_TEXTURE0 etc.</param>
15         /// <param name="target"></param>
16         public override void Bind(uint unit, BindTextureTarget target)
17         {
18             // nothing to do.
19         }
20     }

+BIT祝威+悄悄在此留下版了个权的信息说:

ImageFiller

填充数据就是用 glTexImage2D() 、 glTexStorage2D() 等指令设置Texture的内容。ImageFiller就是封装这一操作的。

 1     /// <summary>
 2     /// build texture‘s content.
 3     /// </summary>
 4     public abstract class ImageFiller
 5     {
 6
 7         /// <summary>
 8         /// build texture‘s content.
 9         /// </summary>
10         /// <param name="target"></param>
11         public abstract void Fill(BindTextureTarget target);
12     }

对于常见的以 System.Drawing.Bitmap 为数据源填充Texture的情形,可以用下面的BitmapFiller。它可以作为1D/2D的Texture对象的填充器。

 1     /// <summary>
 2     /// build texture‘s content with Bitmap.
 3     /// </summary>
 4     public class BitmapFiller : ImageFiller
 5     {
 6         private System.Drawing.Bitmap bitmap;
 7         private int level;
 8         private uint internalformat;
 9         private int border;
10         private uint format;
11         private uint type;
12
13         /// <summary>
14         /// build texture‘s content with Bitmap.
15         /// </summary>
16         /// <param name="bitmap"></param>
17         /// <param name="level">0</param>
18         /// <param name="internalformat">OpenGL.GL_RGBA etc.</param>
19         /// <param name="border">0</param>
20         /// <param name="format">OpenGL.GL_BGRA etc.</param>
21         /// <param name="type">OpenGL.GL_UNSIGNED_BYTE etc.</param>
22         public BitmapFiller(System.Drawing.Bitmap bitmap,
23             int level, uint internalformat, int border, uint format, uint type)
24         {
25             this.bitmap = bitmap;
26             this.level = level;
27             this.internalformat = internalformat;
28             this.border = border;
29             this.format = format;
30             this.type = type;
31         }
32
33         /// <summary>
34         /// build texture‘s content with Bitmap.
35         /// </summary>
36         /// <param name="target"></param>
37         public override void Fill(BindTextureTarget target)
38         {
39             // generate texture.
40             //  Lock the image bits (so that we can pass them to OGL).
41             BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
42                 ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
43             if (target == BindTextureTarget.Texture1D)
44             {
45                 OpenGL.TexImage1D((uint)target, 0, this.internalformat, bitmap.Width, 0, this.format, this.type, bitmapData.Scan0);
46             }
47             else if (target == BindTextureTarget.Texture2D)
48             {
49                 OpenGL.TexImage2D((uint)target, 0, this.internalformat, bitmap.Width, bitmap.Height, 0, this.format, this.type, bitmapData.Scan0);
50             }
51             else
52             { throw new NotImplementedException(); }
53
54             //  Unlock the image.
55             bitmap.UnlockBits(bitmapData);
56         }
57     }

BitmapFiller

还有一个常见的填充方式 glTexStorage2D() ,可以用下面的TexStorageImageFiller实现。

 1     /// <summary>
 2     ///
 3     /// </summary>
 4     public class TexStorageImageFiller : ImageFiller
 5     {
 6         private int levels;
 7         private uint internalFormat;
 8         private int width;
 9         private int height;
10
11         /// <summary>
12         ///
13         /// </summary>
14         /// <param name="levels"></param>
15         /// <param name="internalFormat"></param>
16         /// <param name="width"></param>
17         /// <param name="height"></param>
18         public TexStorageImageFiller(int levels, uint internalFormat, int width, int height)
19         {
20             // TODO: Complete member initialization
21             this.levels = levels;
22             this.internalFormat = internalFormat;
23             this.width = width;
24             this.height = height;
25         }
26
27         /// <summary>
28         ///
29         /// </summary>
30         /// <param name="target"></param>
31         public override void Fill(BindTextureTarget target)
32         {
33             switch (target)
34             {
35                 case BindTextureTarget.Unknown:
36                     break;
37                 case BindTextureTarget.Texture1D:
38                     break;
39                 case BindTextureTarget.Texture2D:
40                     OpenGL.TexStorage2D(TexStorage2DTarget.Texture2D, levels, internalFormat, width, height);
41                     break;
42                 case BindTextureTarget.Texture3D:
43                     break;
44                 case BindTextureTarget.TextureCubeMap:
45                     break;
46                 case BindTextureTarget.TextureBuffer:
47                     break;
48                 default:
49                     break;
50             }
51         }
52     }

TexStorageImageFiller

+BIT祝威+悄悄在此留下版了个权的信息说:

创建Texture

用封装的类型创建Texture的方式如下:

 1 Texture Create(Bitmap bitmap)
 2 {
 3     var texture = new Texture(BindTextureTarget.Texture2D,
 4         new BitmapFiller(bitmap, 0, OpenGL.GL_RGBA32F, 0, OpenGL.GL_BGRA, OpenGL.GL_UNSIGNED_BYTE),
 5         new SamplerParameters(
 6             TextureWrapping.ClampToEdge,
 7             TextureWrapping.ClampToEdge,
 8             TextureWrapping.ClampToEdge,
 9             TextureFilter.Linear,
10             TextureFilter.Linear));
11     texture.Initialize();
12
13     return texture;
14 }

使用Texture

Texutre.Id就是用 glGenTextures() 获得的id。Texture中记录了此Texture的ActiveTexture、Target等属性。配合CSharpGL中的 samplerValue ,我们有:

 1         /// <summary>
 2         /// get <see cref="samplerValue"/> from this texture.
 3         /// </summary>
 4         /// <param name="texture"></param>
 5         /// <returns></returns>
 6         public static samplerValue ToSamplerValue(this Texture texture)
 7         {
 8             return new samplerValue(
 9                 texture.Target,
10                 texture.Id,
11                 texture.ActiveTexture);
12         }

这就可以用到设置shader中需要的Texture上:

this.SetUniform("tex", texture.ToSamplerValue());

封装Framebuffer

过程式的Framebuffer

首先观察一下平时是如何创建和使用Framebuffer对象的。

创建Framebuffer

为关注重点,这里直接传入Texture的Id。

 1 uint Create(int width, int height, uint textureId)
 2 {
 3     // create framebuffer.
 4     var frameBufferId = new uint[1];
 5     glGenFramebuffers(1, frameBufferId);
 6     glBindFramebuffer(OpenGL.GL_FRAMEBUFFER, frameBufferId);
 7
 8     // attach texture as a color buffer.
 9     glFramebufferTexture2D(OpenGL.GL_FRAMEBUFFER, OpenGL.GL_COLOR_ATTACHMENT0, OpenGL.GL_TEXTURE_2D, textureId, 0);
10
11     // create a depth buffer.
12     var renderbufferId = new uint[1];
13     glGenRenderbuffers(1, renderbufferId);
14     glBindRenderbuffer(OpenGL.GL_RENDERBUFFER, renderbufferId[0]);
15     glRenderbufferStorage(OpenGL.GL_RENDERBUFFER, OpenGL.GL_DEPTH_COMPONENT, width, height);
16
17     // attach depth buffer.
18     glFramebufferRenderbuffer(OpenGL.GL_RENDERBUFFER, OpenGL.GL_DEPTH_ATTACHMENT, OpenGL.GL_RENDERBUFFER, renderbufferId);
19
20     glBindFramebuffer(OpenGL.GL_RENDERBUFFER, 0);
21
22     return frameBufferId;
23 }

使用Framebuffer

使用方式与Texture类似,只要绑定就可以了。

    glBindFramebuffer(OpenGL.GL_FRAMEBUFFER, frameBufferId);

用完再解绑。

    glBindFramebuffer(OpenGL.GL_FRAMEBUFFER, 0);

封装的Framebuffer

Framebuffer就是一个盒子,单独创建一个Framebuffer基本上是没什么用的。必须Attach一些colorbuffer/depthbuffer/texture才能发挥作用。

一个Framebuffer能够绑定多个texture和colorbuffer,只能绑定一个depthbuffer。

Renderbuffer

colorbuffer和depthbuffer都属于Renderbuffer的一种,其创建方式相同,只不过有一个标识其为colorbuffer还是depthbuffer的标志不同。

创建Renderbuffer很简单。

 1     /// <summary>
 2     /// Create, update, use and delete a renderbuffer object.
 3     /// </summary>
 4     public partial class Renderbuffer
 5     {
 6         uint[] renderbuffer = new uint[1];
 7         /// <summary>
 8         /// Framebuffer Id.
 9         /// </summary>
10         public uint Id { get { return renderbuffer[0]; } }
11
12         /// <summary>
13         /// Create, update, use and delete a renderbuffer object.
14         /// </summary>
15         /// <param name="width"></param>
16         /// <param name="height"></param>
17         /// <param name="internalformat">GL_DEPTH_COMPONENT, GL_RGBA etc.</param>
18         /// <param name="bufferType"></param>
19         public Renderbuffer(int width, int height, uint internalformat, RenderbufferType bufferType)
20         {
21             this.Width = width;
22             this.Height = height;
23             this.BufferType = bufferType;
24
25             glGenRenderbuffers(1, renderbuffer);
26             glBindRenderbuffer(OpenGL.GL_RENDERBUFFER, renderbuffer[0]);
27             glRenderbufferStorage(OpenGL.GL_RENDERBUFFER,
28                 internalformat, width, height);
29         }
30
31         public int Width { get; set; }
32         public int Height { get; set; }
33         public RenderbufferType BufferType { get; private set; }
34     }
35
36     public enum RenderbufferType
37     {
38         DepthBuffer,
39         ColorBuffer,
40     }

+BIT祝威+悄悄在此留下版了个权的信息说:

创建Framebuffer

创建Framebuffer也很简单,实际上只是调用了一个 glGenFramebuffers(1, frameBuffer); 命令。

 1     /// <summary>
 2     /// Create, update, use and delete a framebuffer object.
 3     /// </summary>
 4     public partial class Framebuffer : IDisposable
 5     {
 6         uint[] frameBuffer = new uint[1];
 7         /// <summary>
 8         /// Framebuffer Id.
 9         /// </summary>
10         public uint Id { get { return frameBuffer[0]; } }
11
12         /// <summary>
13         /// Create an empty framebuffer object.
14         /// </summary>
15         public Framebuffer()
16         {
17             glGenFramebuffers(1, frameBuffer);
18         }
19     }
20
21     /// <summary>
22     ///
23     /// </summary>
24     public enum FramebufferTarget : uint
25     {
26         /// <summary>
27         /// used to draw(write only) something.
28         /// </summary>
29         DrawFramebuffer = OpenGL.GL_DRAW_FRAMEBUFFER,
30         /// <summary>
31         /// used to read from(read only).
32         /// </summary>
33         ReadFramebuffer = OpenGL.GL_READ_FRAMEBUFFER,
34         /// <summary>
35         /// both read/write.
36         /// </summary>
37         Framebuffer = OpenGL.GL_FRAMEBUFFER,
38     }

使用Framebuffer

使用方式与Texture类似,只要绑定就可以了。

    framebuffer.Bind();// glBindFramebuffer(OpenGL.GL_FRAMEBUFFER, framebufferId);

用完再解绑。

    framebuffer.Unbind();// glBindFramebuffer(OpenGL.GL_FRAMEBUFFER, 0);

这与未封装的使用方式没什么区别。

总结

基于目前我对Texture和Framebuffer的了解,现在只能封装到这个地步。

+BIT祝威+悄悄在此留下版了个权的信息说:

时间: 2024-10-03 21:50:04

CSharpGL(29)初步封装Texture和Framebuffer的相关文章

小记:对Android网络下载工具的初步封装!(包括json,字符串下载(volley),和图片下载(glide))

import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.widget.ImageView; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError

DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)

一.DAO模式简介 DAO即Data Access Object,数据访问接口.数据访问:故名思义就是与数据库打交道.夹在业务逻辑与数据库资源中间. DAO模式实际上是两个模式的组合,即Data Accessor (数据访问者)模式和 Active Domain Object(领域对象)模式.Data Accessor 模式实现了数据访问和业务逻辑的分离:Active Domain Object 模式实现了业务数据的对象化封装. 需要注意的是,DAO设计模式是Java EE中的设计模式,而非Ja

MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)

[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4059514.html 联系方式:[email protected] [正文] 一.DAO模式简介 DAO即Data Access Object,数据访问接口.数据访问:故名思义就是与数据库打交道.夹在业务逻辑与数据库资源中间. DAO模式实际上是两个模式的组合,即Data Accessor (数据

自定义控件三部曲之绘图篇(十七)——为Bitmap添加阴影并封装控件

前言:再重复一遍我很喜欢的一句话,送给大家:迷茫,本就是青春该有的样子 ,但不要让未来的你,讨厌现在的自己 上篇给大家讲解了如何控件添加阴影效果,但是在为Bitmap图片添加阴影时,却没办法添加具有指定颜色的阴影,这篇我们就来使用自定义的控件及自定义属性来初步封装下控件.前方高能预警--本篇内容涉及内容较多,难度较大,需要多加思考. 一.使用BlurMaskFilter为图片构造定色阴影效果 上面我们讲了通过setShadowLayer为图片添加阴影效果,但是图片的的阴影是用原图形的副本加上边缘

Android项目开发全程(三)-- 项目的前期搭建、网络请求封装是怎样实现的

在前两篇博文中已经做了铺垫,下面咱们就可以用前面介绍过的内容开始做一个小项目了(项目中会用到Afinal框架,不会用Afinal的童鞋可以先看一下上一篇博文),正所谓麻雀虽小,五脏俱全,这在里我会尽量的将前期的项目搭建做的相对实用一些,以便后期可以有效的实现团队协作和项目维护.一开始可能会看起来麻烦些,可能会觉得还不如直接用简单的方式去实现来的方便,磨刀不误砍柴工嘛,要想后期开发效率高一些,前期就不要图省事了. 一个项目肯定不是一蹴而就的,咱们一步一步来,本篇博文先详细介绍项目搭建.通过url地

【JavaScript 封装库】BETA 1.0 测试版发布!

1 /* 2 源码作者: 石不易(Louis Shi) 3 联系方式: http://www.shibuyi.net 4 =================================================================================================== 5 程序名称: JavaScript 封装库 BETA 1.0 版 6 迭代版本: Prototype 7 功能总数: 44 个 8 新增总数: 30 个 9 删除总数: 0 个

前后分离模型之封装 Api 调用

Ajax 和异步处理 调用 API 访问数据采用的 Ajax 方式,这是一个异步过程,异步过程最基本的处理方式是事件或回调,其实这两种处理方式实现原理差不多,都需要在调用异步过程的时候传入一个在异步过程结束的时候调用的接口.比如 jQuery Ajax 的 success 就是典型的回调参数.不过使用 jQuery 处理异步推荐使用 Promise 处理方式. Promise 处理方式也是通过注册回调函数来完成的.jQuery 的 Promise 和 ES6 的标准 Promise 有点不一样,

展讯LCD浏览之前记

基于展讯sc7731 - Android 5.1 代码分析浏览.将屏蔽细节,把握整体,并且不涉及其他设备和LCD的交互. 以下对sc7731 lcd大体流程进行简要说明. 第一,lcd 的两个阶段 1. 在uboot引起系统阶段,大约1~5秒左右,需要打印一个厂商log.这里对驱动要求非常简单,只要能打印log即可. (下面皆以lcd_ili9486s1_mipi.c为例)  驱动文件放置路径: u-boot64/drivers/video/sprdfb/lcd/ 添加新屏时需要修改的文件分别为

开源工具DbUtils的使用(数据库的增删改查)

一.DbUtils简介: DBUtils是apache下的一个小巧的JDBC轻量级封装的工具包,其最核心的特性是结果集的封装,可以直接将查询出来的结果集封装成JavaBean,这就为我们做了最枯燥乏味.最容易出错的一大部分工作. 下载地址:http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi 下载上图中的红框部分,然后解压.解压之后的文件如下 : 上图中红框部分的文件就是我们所需要的内容. 二.核心方法: Db