unity的 paint texturepaint java里为什么没有纹理

今天看啥 热点:
unity纹理总结,unity纹理
转载请注明出处
我们知道手游的表现力和美术密不可分,美术资源的滥用往往会导致大量的美术返工。所以根据游戏的需要制定合理的美术规格十分重要的。写这篇文章的目的在于解决两个问题。第一,美术作图有怎么样的规范,第二,图片unity怎么处理最好。
因为我们项目是2D项目,很少涉及3D模型,我们这里的美术资源就特指2D Texture。
特别的,我们在这里只研究texture type为sprite 的情况。因为场景中的object的component只有sprite render,而且这样也覆盖了gui。
首先介绍一下sprite的各个参数的简单含义。
Sprite Mode: single独立图片multiple& 多张有关联图片,可以editor切割
Packing tag: &同样的tag可以在sprite packer中打包图集,pro only
Pixelstounit: &单元sprite像素数量,越大越精细,默认100
Pivot:&&&&& &中心点,设计到rotate的时候特别要当心
Mipmaps:&& 多重纹理,内存多1/3。做3D的话建议详细了解一下
Fitermode:& 被拉伸时候的填充模式
Maxsize:&&& 图片大小
Format:&&&& 纹理格式
详情参见/Manual/class-TextureImporter.html
与纹理相关的几个方面:内存大小,安装包大小和drawcall。当然还有cpu,gpu处理速度,读取速度,这里就不讨论了,我们专心讨论以上三点。
首先讨论内存和安装包:
Unity资源选中图片,inspector显示的大小,即读入内存的大小。我们知道,unity可以读取多种图片格式,它内部会处理成为自己的专门格式,打包的时候会以assetbundle方式存放。所以,内存的大小依赖于纹理参数,而与图片是什么格式的没有关系的。而打包成为assetbudle和内存相关同时也和原图的大小相关。(其实取决于原图大小和纹理参数)。我们可以简单地认为内存占用多了,安装包就大。
我们首先来看一下psd图片直接放在unity的情况。(maxsize= 1024 &format = truecolor)
再看一下maxsize,format对内存及安装包的影响。
上面两份表格中分辨率的用的是同样的图片。我们可以看出,IOS上可以压缩(POT图,正方形图)对内存和包大小有很大的优化,而format和maxsize同样也有影响。
抛开实验图片不谈,针对我们的游戏(大量透明图,色彩数广)对原图(大于)的不同处理会有不同的效果:
1 maxsize调整为512。稍微失真,可以接受。
2 format由RGBA32调整为 RGBA16。完全失真,不能接受。
3 IOS压缩为PVRTC4bit。失真非常小,完全可以接受。
4安卓压缩为RGBA16。完全失真,不能接受。
再看一份表格,同样的图片表现,美术在作图时处理为不同分辨率。
其中的图片内存直接从4M到0.5M,安装包减少4倍。优势实在太明显了,遗憾的是,它只支持IOS,安卓却不可以。
再次我们讨论drawcall
对于纹理首先想到的就是纹理合并。对于spritepacker,官方文档中“For optimal performance”主要有两点,即对于empty space和 drawcall的影响。于是对于drawcall的讨论我们这里变成对spritepacker的讨论
详情参见/Manual/SpritePacker.html。
Sprite render同一材质不同纹理依旧会产生多个drawcall,而纹理的合并会减少drawcall。实际上在我们的游戏中,摄像机范围内的图片总是有限的,drawcall的数量很低的,所以我们的重点不在这里,而是spritepacker对空间的影响。
&&&&&&&& 如果我们对场景中大图小图全图打包会如何,场景加载时候无论用到什么图,都会载入图集的内存,如果只用到了小图,那么图集的出场无异于牛刀杀鸡,这也是为什么好多项目谈经验的时候只对GUI的图进行图集处理,并不是NGUI做了这份工作,以前没有UGUI的时候没做。
&&&&&&&& 而我们的场景中基本都是背景图,所以并不适合打包进图集,而小的“零件图片”却可以被pack,多余的加载可以换来IO的节省,这样的规划应该是比较合理的。
&&&&&&&& 关于spritepacker其实还有个问题没有研究清楚。Pack后的图集是放在library的cache里面的,library添加到SVN的ignore里面的。按照官方说法,如果cache没有图集,则会再次pack。可是我们知道,pack的时候可以定制的。改变pack方式难道不保存在一个setting文件里面传上去吗?还是在library文件里面被ignore掉了。前面我在思考这样一个问题:
如果美术给的图是NPOT的多张RGBA32图,打包到了一个的图中,选择的是定制的spritepacker,设置图集的entry.settings.format =
TextureFormat.PVRTC_RGBA4,是否意味着我对这10张都进行了合并成一个RGBA32格式的图集然后进行对图集PVRTC压缩?如果是这样的话,那么不就是可以进一步优化了?不过话说回来,小图的表现力就那么微观,稍微一点失真还是可以看出来的,另一方面优化的程度也没有那么大,整个等项目后期处理时候再考虑吧。
总结上面,针对我们项目的处理方案:
美术作图:Height/width 256以下图片任意作图,因为好多与UI类似。
Unity处理:选择RGBA32做spritepacker,是否可以压缩为PVRTC再做考量。
美术作图:Height/width 256+的图片,做成POT图片
Unity处理:的maxsize设置为(失真可接受),PVRTC压缩。
上面主要考虑的是IOS的情况。如果安卓的话先留两个思路吧。第一个&“目前主流的Android机型基本都支持ETC1格式压缩。但ETC1只能支持非Alpha通道的图片压缩。所以一般把Alpha通道图分离出来,绘制到GPU显存时,a值从Alpha图里获取,无Alpha通道的图就可以使用ETC1压缩。”第二点依旧从maxsize做处理。以上的讨论和总结都是针对我们自己的项目而言。不同项目应该有不同关注点,具体参数的理解还是要再看看文档和经验。希望文章能帮助到有需要的同学,不对之处希望给予指正。
相关搜索:
相关阅读:
相关频道:
Android教程最近更新Unity3D基础教程3-4:2D纹理(Texture 2D)
Unity 手册-&用户指南-&与资产合作-&纹理2D
Textures bring your Meshes, Particles, and interfaces to life! They are image or movie files that you lay over or wrap around your objects. As they are so important, they have a lot of properties. If reading this for the first time, jump down to , and return to the actual settings when you need a reference.
纹理带给你的网格、粒子及界面生命力。它们是图像或电影你覆盖或环绕你的对象。当它们引入时,它们有许多属性。如果在第一时间渲染,跳至(详细资料处),并返回动作设置在你需要一个引用时。
The shaders you use for your objects put specific requirements on which textures you need, but the basic principle is that you can put any image file inside your project. If it meets the size requirements (specified below), it will get imported and optimized for game use. This extends to multi-layer Photoshop or TIFF files - they are flattened on import, so there is no size penalty for your game.
为你的对象使用阴影放置指定的需求在你需要的纹理上,但是基本原则是你可以放置任何图像文件在你的项目里。如果它满足需求大小(在下面指定),它将获得引入并为游戏使用组织。这个扩展到多层Photoshop或TIFF文件它们是在引入上变平,因此没有大小损失你的游戏。
Properties 属性
The Texture Inspector looks a bit different from most others: 纹理检视器面板看起来与其它大多数的有点不同
The top section contains a few settings, and the bottom part contains import settings and a texture preview.
顶部部分包含几个设置,底部部分包含引入设置和纹理预览
Aniso Level
Increases texture quality when viewing the texture at a steep angle. Good for floor and ground textures, see .
当子一个陡峭角度观看纹理时,增长纹理质量。能担当地板与地面纹理,见下面。
Filter Mode
Selects how the Texture is filtered when it gets stretched by 3D transformations:
选取当纹理通过3D转换获得伸展时纹理如何被过滤
No Filtering
The Texture becomes blocky up close
纹理变为斑驳向上接近
The Texture becomes blurry up close
纹理变为模糊向上接近
Like Bilinear, but the Texture also blurs between the different mip levels
像双线性,但纹理也在不同人工处理级别之间模糊
Selects how the Texture behaves when tiled:
选取当纹理平铺时,纹理如何运转
The Texture repeats (tiles) itself
纹理它自己重复
The Texture's edges get stretched
纹理的边缘获得伸展
Import Settings 引入设置
Textures all come from image files in your Project Folder. How they are imported is specified by the texture's Import Settings. You change these by selecting the file texture in the Project View and modifying the Import Settings in the Inspector.
纹理全部来自图象文件在你的项目文件夹里。它们如何被引入是通过纹理的引入设置指定的。你更改它们通过选择纹理文件在项目视图里并修改引入设置在检视器面板。
The Texture Import Settings dialog 纹理引入设置对话框
Max Texture Size
最大纹理大小
The maximum imported texture size. A lot of artists prefer to work with huge textures - scale the texture down to a suitable size with this.
最大值引入纹理大小。许多艺术家更愿意与巨大纹理一起工作&伸展纹理到合适的大小
Texture Format
What internal representation is used for the texture. This is a tradeoff between size and quality. In the examples below we show the final size of a in-game texture of 256 by 256 pixels:什么内部表示应用与纹理。这是大小与质量之间的折衷。在下面的例子里,我们显示最终规模由256像素的游戏内部纹理:
RGB Compressed
RGB压缩DXT1
Compressed RGB texture. This is the most common format for diffuse textures. 4 bits per pixel (32 KB for a 256x256 texture).
压缩RGB纹理。这是常见的漫射纹理格式。4位每像素(32KB的256*256纹理)
RGBA Compressed
RGBA 压缩DXT5
Compressed RGBA texture. This is the main format used for diffuse & specular control textures. 1 byte/pixel (64 KB for a 256x256 texture).
压缩RGB纹理。这是主要的漫射与反射控制纹应用的主要理格式。每像素1位(64KB的256*256纹理)
RGB 16 bit
65 thousand colors with no alpha. Compressed DXT formats use less memory and usually look better. 128 KB for a 256x256 texture.
65000没有alpha的颜色。压缩DXT格式用于减少内存以及通常好看。128K的256*256纹理。
RGB 24 bit
Truecolor but without alpha. 192 KB for a 256x256 texture.
没有alpha的真彩。192K的256*256纹理
Alpha 8 bit
8位的Alpha
High quality alpha channel but without any color. 64 KB for a 256x256 texture.
无任何颜色的高质量alpha通道。64K的256*256纹理。
RGBA 16 bit
16位的RGBA
Low-quality truecolor. Has 16 levels of red, green, blue and alpha. Compressed DXT5 format use less memory and usually look better. 128 KB for a 256x256 texture.
低质量真彩。有16位级别的红、绿、蓝以及alpha。压缩DXT5格式的使用少的内存并通产好看。128k的256*256纹理。
RGBA 32 bit
32位的RGBA
Truecolor with alpha - this is the highest quality. At 256 KB for a 256x256 texture, this one is expensive. Most of the time, DXT5 offers sufficient quality at a much smaller size. The main place this is used is for bump maps, as DXT compression there often carries a visible quality loss.
有alpha的真彩&这是最高的质量。在256K的256*256纹理,据此之一是昂贵的。在多数情况下,DXT5提供了一个更小的大小足够的质量。主要地方是用于凹凸图,DXT压缩经常带有明显的质量损失。
Build Alpha From Grayscale
从灰度级建立Alpha
If enabled, an alpha transparency channel will be generated by the image's existing values of light & dark.
如果启用,一个alpha透明性通道将通过图象的存在明暗的值产生
Non Power of 2 sizes
非2的幂的大小
If texture has non-power-of-two size, this will define a scaling behavior at import time (for more info see
section below):
如果纹理有两个幂的大小,这将定义一个在引入时的伸展行为(更多信息看下面的纹理大小节)。
Keep original
Texture will be padded to the larger power-of-two size for use with GUITexture component.
纹理将填补大的两个幂的大小与GUI纹理组件一起使用。
Scale to nearest
最近的规模
Texture will be scaled to the nearest power-of-two size at import time. For instance 257x511 texture will become 256x512. Note that PVRTC formats require textures to be square (width equal to height), therefore final size will be upscaled to 512x512.
在引入时,纹理将被伸缩到最近两个幂的大小。对于257*511纹理实例将变为256*512.注意PVRTC格式需要纹理是正方形(宽高相等),因此最终规模将扩大到512*512.
Scale to larger
Texture will be scaled to the larger power-of-two size at import time. For instance 257x511 texture will become 512x512.
在引入时,纹理将缩放到大的两个幂尺寸。对于257*511纹理实例将变为512*512.
Scale to smaller
Texture will be scaled to the smaller power-of-two size at import time. For instance 257x511 texture will become 256x256.
在引入时,纹理将缩放到小的两个幂尺寸。对于257*511纹理实例将变为256*256.
Generate Cube Map
产生立方体映射
Generates a cubemap from the texture using different generation methods.
产生一个立方体映射从纹理使用不同方式产生。
Is Readable
Select this to enable access to the texture data from the scripts (GetPixels, SetPixels and other
functions). Note however that a copy of the texture data will be made doubling the amount of memory required for texture asset. Use only if absolutely necessary. Disabled by default.
选取它启用访问纹理数据从脚本(GetPixels, SetPixels以及其它纹理2D函数)。不过注意,纹理数据的副本将使用双倍内存需要的纹理资产。使用只读绝对必要。默认禁用。
Generate Mip Maps
产生Mip映射
Select this to enable mip-map generation. Mip maps are smaller versions of the texture that gets used when the texture is very small on screen. For more info, see
选取启用mip映射生成。Mip映射是当纹理非常小的显示在屏幕上时获得使用的小的纹理版本。更多信息,查看下面的mip映射
Correct Gamma
Select this to enable per-mip-level gamma correction.
选取启用每mip级别纠正
Border Mip Maps
边界Mip映射
Select this to avoid colors seeping out to the edge of the lower Mip levels. Used for light cookies (see below).
选取是为了避免颜色渗漏到低mip级别边缘外部。光波烹调使用(看下面)
Mip Map Filtering
Mip映射过滤
Two ways of mip map filtering is available to optimize image quality:
Mip映射过滤的两种方法是可用的优化图形质量。
The simplest way to fade out the mipmaps - the mip levels become smoother and smoother as they go down in size.
简单的方法淡出mip映射&mip级别变为平滑及平滑作为它们下降的尺寸。
A sharpening Kaiser algorithm is run on the mip maps as they go down in size. If your textures are too blurry in the distance, try this option.
Kaiser钝化算法是运行在mip映射上作为它们下降的尺寸。如果你的纹理是在远处太模糊,尝试这个选项。
Fade Out Mips
Enable this to make the mipmaps fade to gray the mip levels progress. This is used for detail maps.启用它使mip映射淡出到灰色mip级别处理。这被用于详细映射。
Fade Out start
The first mip level to begin fading out at.
第一mip级别开始淡出。
Fade Out End
The mip level where the texture is completely grayed out.
纹理完成的灰色输出那里的mip级别。
Generate Bump Map
产生凹凸映射
Enable this to turn the color channels into a format suitable for real-time bumpmapping. For more info, see , below.
启用它去更改颜色通道对到一个适合格式的实时凹凸。更多信息,查看凹凸映射,在下面。
Bumpiness崎岖不平
Control the amount of bumpiness. 控制崎岖不平的数量
Filtering 过滤
Determine how the bumpiness is calculated: 确认崎岖不平如何计算的。
Standard 标准
This generates normal maps that are quite smooth. 这样生成的正常映射十分平滑。
Sobel 索贝尔
The Sobel filter generates normal maps that are sharper than Standard.
Sobel过滤器产生比正常标准清晰的映射。Details 详细资料
欢迎与本站!
QQ交流群1:
QQ交流群2:TexturePaint (Java 2 Platform SE 5.0)
JavaTM&2&PlatformStandard&Ed. 5.0
类 TexturePaint
java.awt.TexturePaint
所有已实现的接口: ,
public class TexturePaintextends implements
TexturePaint 类提供一种用被指定为
的纹理填充
的方式。因为 BufferedImage 数据由 TexturePaint 对象复制,所以 BufferedImage 对象的大小应该小一些。在构造时,纹理定位在用户空间中指定的
的左上角。计算纹理在设备空间中的位置的方式是,在用户空间中的所有方向上无限制地总体复制指定 Rectangle2D,然后将 BufferedImage 映射到各个复制的 Rectangle2D。
另请参见:,
&&&&&&&&&&构造 TexturePaint 对象。
&deviceBounds,
&userBounds,
&&&&&&&&&&创建并返回用于生成颜色模式的上下文。
&&&&&&&&&&返回定位纹理图像并设置其大小的固定矩形的副本。
&&&&&&&&&&返回用于填充形状的 BufferedImage 纹理。
&&&&&&&&&&返回此 TexturePaint 的透明模式。
, , , , , , , , , ,
TexturePaint
public TexturePaint(&txtr,
构造 TexturePaint 对象。
参数:txtr - 具有用于绘制的纹理的 BufferedImage 对象anchor - 用户空间中用于定位和复制纹理的 Rectangle2D
getImage()
返回用于填充形状的 BufferedImage 纹理。
返回:一个 BufferedImage。
getAnchorRect
getAnchorRect()
返回定位纹理图像并设置其大小的固定矩形的副本。
返回:用来将此 TexturePaint 固定并设置其大小的 Rectangle2D。
createContext
createContext(&cm,
&deviceBounds,
&userBounds,
创建并返回用于生成颜色模式的上下文。
指定者:接口
参数:cm - 接收 Paint 数据的 。此参数只用作一个提示。deviceBounds - 要呈现的图形原语的设备空间边界框userBounds - 要呈现的图形原语的用户空间边界框xform - 从用户空间到设备空间的 hints - 可用于指定模式的最终呈现方式的
返回:用于生成颜色模式的 。另请参见:
getTransparency
public int getTransparency()
返回此 TexturePaint 的透明模式。
指定者:接口
返回:整数值形式的此 TexturePaint 的透明模式。另请参见:
JavaTM&2&PlatformStandard&Ed. 5.0
有关更多的 API 参考资料和开发人员文档,请参阅 。该文档包含更详细的、面向开发人员的描述,以及总体概述、术语定义、使用技巧和工作代码示例。 版权所有 2004 Sun Microsystems, Inc. 保留所有权利。 请遵守。另请参阅。Unity Shaders 基础篇(三) 纹理与透明度
纹理映射的概念很好理解
有点类似于铺床单,把对应的角放好,然后拉平即可
也可以理解成穿衣服,把衣服相应位置拖到身体的对应位置即可
从图形学角度来看,就是把一个三角形的三个顶点对应贴图的三个点,然后把在贴图中的三角形中的像素全部插值到真正的模型中
纹理映射的概念很好理解. 有点类似于铺床单,把对应的角放好,然后拉平即可. 也可以理解成穿衣服,把衣服相应位置拖到身体的对应位置即可. 从图形学角度来看,就是把一个三角形的三个顶点对应贴图的三个点,然后把在贴图中的三角形中的像素全部插值到真正的模型中.
Shader "Cg shader with single texture" {
Properties {
_MainTex ("Texture Image", 2D) = "white" {}
// a 2D texture property that we call "_MainTex", which should
// be labeled "Texture Image" in Unity's user interface.
// By default we use the built-in texture "white"
// (alternatives: "black", "gray" and "bump").
SubShader {
#pragma vertex vert
#pragma fragment frag
uniform sampler2D _MainT
// a uniform variable refering to the property above
// (in fact, this is just a small integer specifying a
// "texture unit", which has the texture image "bound"
// Unity takes care of this).
struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0; //每个顶点对应的uv值
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
vertexOutput vert(vertexInput input)
output.tex = input.
// Unity provides default longitude-latitude-like
// texture coordinates at all vertices of a
// sphere mesh as the input parameter
// "input.texcoord" with semantic "TEXCOORD0".
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);//屏幕空间坐标
float4 frag(vertexOutput input) : COLOR
return tex2D(_MainTex, input.tex.xy);
//屏幕每个点对应的uv坐标
// look up the color of the texture image specified by
// the uniform "_MainTex" at the position specified by
// "input.tex.x" and "input.tex.y" and return it
Fallback "Unlit/Texture"
效果图如下:
代码简单分析如下:vcD4NCjxwcmUgY2xhc3M9"brush:">
struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0; //每个顶点对应的uv值
首先,float4 vertex : POSITION;我们得到了模型每个顶点的坐标(模型空间).
然后,float4 texcoord : TEXCOORD0;代表的是这些顶点对应在贴图的坐标点(二维纹理空间).
由于我们要传递给frag函数才能绘图.
output.tex = input.
在这里我们把纹理坐标传给vertexOutput.
当frag函数得到这个output时,每个渲染的三角形的像素都由其三个顶点上的纹理坐标进行插值. 然后我们通过去查找纹理上的颜色值即可正常渲染了.
重复和偏移
当我们在Properties里面加入了Texture后,会发现多出了四个额外的数值选项:
在我们上面的简易shader中并未进行处理.
这里进行说明一下:
其中Tiling默认的含义是重复,而Offset代表的是偏移. 这里默认的意思是大家约定俗成的东西,但是并不一定非要这么用.(比如上文我们就用texture coordinate来传递模型的坐标信息) 而实际上这些数据会传给
uniform sampler2D _MainT
uniform float4 _MainTex_ST;
中的_MainTex_ST.
其中Tiling的xy值会传给_MainTex_ST的xy.
而Offset的xy值会传给_MainTex_ST的zw.
Shader "Cg shader with single texture" {
Properties {
_MainTex ("Texture Image", 2D) = "white" {}
// a 2D texture property that we call "_MainTex", which should
// be labeled "Texture Image" in Unity's user interface.
// By default we use the built-in texture "white"
// (alternatives: "black", "gray" and "bump").
SubShader {
#pragma vertex vert
#pragma fragment frag
uniform sampler2D _MainT
uniform float4 _MainTex_ST;
// tiling and offset parameters of property
struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
vertexOutput vert(vertexInput input)
output.tex = input.
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
float4 frag(vertexOutput input) : COLOR
return tex2D(_MainTex,
_MainTex_ST.xy * input.tex.xy + _MainTex_ST.zw);
// texture coordinates are multiplied with the tiling
// parameters and the offset parameters are added
Fallback "Unlit/Texture"
接下来是效果图:
这里再次解释一下关键语句:
float4 frag(vertexOutput input) : COLOR
return tex2D(_MainTex,
_MainTex_ST.xy * input.tex.xy + _MainTex_ST.zw);
// texture coordinates are multiplied with the tiling
// parameters and the offset parameters are added
首先我们把这行函数分开来看.
_MainTex_ST.xy代表的是原来的纹理坐标.
现在我们假设_MainTex_ST.xy即Tiling的xy为(2,2). 我们可以知道在原来的计算中 x.y都为1可以达到纹理的边缘,但是现在0.5就可以达到原来的效果. 这样就代表纹理其实重复了.
额外要注意的是当我们用tex2D来取纹理坐标时,输入值是可以不在[0,1]范围的. 那么当超出范围了会产生什么效果呢? 这里是由Texture本身的导入选项来决定的.
这里可能展示的不明显,大家可以自己试验调整下. 实际上当Texture以repeat显示时,它只会取小数部分.而以clamp方式显示时将会被截断.
先上图演示一个透明度的例子:
上图所示的绿色其实是一个sphere. 而cube是放在它的后面.
然后这里先列出代码:
Shader "Cg shader using blending" {
SubShader {
Tags { "Queue" = "Transparent" }
// draw after all opaque geometry has been drawn
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha // use alpha blending
#pragma vertex vert
#pragma fragment frag
float4 vert(float4 vertexPos : POSITION) : SV_POSITION
return mul(UNITY_MATRIX_MVP, vertexPos);
float4 frag(void) : COLOR
return float4(0.0, 1.0, 0.0, 0.5);
// the fourth component (alpha) is important:
// this is semitransparent green
上述代码中,最关键的语句是:
Blend SrcAlpha OneMinusSrcAlpha
这个其实是一个固定管线的配置,意思就是我们不能动态的更改这个函数,只能提前配置.
而配置的公式为:
Blend {code for SrcFactor} {code for DstFactor}
其中的src就是我们通过frag函数计算出来的frag颜色,但是还未进行写入. 而Dst就是已经在屏幕上的颜色. 而所谓的Blend操作就是:
最终颜色=SrcFactor*fragColor+ DstFactor*pixelColor
这里的命名方式是按照OpenGL的习惯. fragColor代表是我们计算的fragColor然后传递给framebuf. 而pixelColor就是在framebuf里面已经存在的颜色. 完整的code(factor)列表在.
一个简明的blend factor列表:
(图片在自于)
这里做个简单的补充:
其中 pixel_color.aaaa指的就是(a,a,a,a) 其中a为pixel_color的alpha值.
关于ZWrite Off
这里举几个例子讲下为什么我们要将深度值关闭.
首先, 假设我们先渲染了sphere. 然后渲染cube. 由于透明物体在前,写入了sphere的z值. 然后渲染cube,由于cube在后面这样就会导致cube的颜色值不会被写入.
但是有人可能会产生疑问,我们为何不先渲染非透明的然后渲染透明的? 但是也会产生问题:
比如 A(透明) B(透明) C(非透明). 我们先渲染C. 然后渲染A. 这时A比C离屏幕更近,所以A的z值被写入. 然后这里B相对于C离屏幕离得更近.但是B可能和A有部分重合或者在A的后方. 所以B的一些元素导致没有被渲染到屏幕上.
这与我们前面讨论的相关. 意思就是放到透明通道. 这里起的作用就是先渲染非透明,再渲染透明的.
为何要这样做? 这里是因为防止A(非透明)B(透明)C(非透明)的情况出现.因为B是不写入Z值,这种情况下, 如果先渲染C然后B然后A的话,B就会被覆盖.举例屏幕的顺序可能是 B
问题仍未解决
因为透明物体的渲染顺序仍然可能会导致出现画面的异常. 比如渲染两个只是轻微透明的物体,那么后渲染的那个明显会贡献主要的颜色.
半透明问题
与透明有关的纹理有两种方式,一种是discard 一种是blend.
在wikibook上有多次重申discard是种不好的方案.
不知道现在有没有解决.等以后深入后再进行测试.(待补充)
下面上两个效果图:
左侧代码如下:
Shader "Cg texturing with alpha discard" {
Properties {
_MainTex ("RGBA Texture Image", 2D) = "white" {}
_Cutoff ("Alpha Cutoff", Float) = 0.5
SubShader {
Cull Off // since the front is partially transparent,
// we shouldn't cull the back
#pragma vertex vert
#pragma fragment frag
uniform sampler2D _MainT
uniform float _C
struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
vertexOutput vert(vertexInput input)
output.tex = input.
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
float4 frag(vertexOutput input) : COLOR
float4 textureColor = tex2D(_MainTex, input.tex.xy);
if (textureColor.a & _Cutoff)
// alpha value less than user-specified threshold?
// yes: discard this fragment
return textureC
Fallback "Unlit/Transparent Cutout"
右侧代码如下:
Shader "Cg semitransparent colors based on alpha" {
Properties {
_MainTex ("RGBA Texture Image", 2D) = "white" {}
SubShader {
Tags {"Queue" = "Transparent"}
Cull Front // first render the back faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha
// blend based on the fragment's alpha value
#pragma vertex vert
#pragma fragment frag
uniform sampler2D _MainT
struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
vertexOutput vert(vertexInput input)
output.tex = input.
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
float4 frag(vertexOutput input) : COLOR
float4 color =
tex2D(_MainTex, input.tex.xy);
if (color.a & 0.5) // opaque back face?
color = float4(0.0, 0.0, 0.2, 1.0);
// opaque dark blue
else // transparent back face?
color = float4(0.0, 0.0, 1.0, 0.3);
// semitransparent green
Cull Back // now render the front faces
ZWrite Off // don't write to depth buffer
// in order not to occlude other objects
Blend SrcAlpha OneMinusSrcAlpha
// blend based on the fragment's alpha value
#pragma vertex vert
#pragma fragment frag
uniform sampler2D _MainT
struct vertexInput {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
struct vertexOutput {
float4 pos : SV_POSITION;
float4 tex : TEXCOORD0;
vertexOutput vert(vertexInput input)
output.tex = input.
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
float4 frag(vertexOutput input) : COLOR
float4 color = tex2D(_MainTex, input.tex.xy);
if (color.a & 0.5) // opaque front face?
//color = float4(0.0, 1.0, 0.0, 1.0);
// opaque green
else // transparent front face
color = float4(0.0, 0.0, 1.0, 0.3);
// semitransparent dark blue
Fallback "Unlit/Transparent"
代码没什么可讲的,就是综合运用下前面所讲的知识.

我要回帖

更多关于 texture paint 的文章

 

随机推荐