我想知道如何将此表面着色器代码转换为Vertex / Fragment pragma:
Shader "Custom/Diamond Opaque Test" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
_SpecColor ("Specular Color", Color) = (0.5,0.5,0.5,1)
_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
_RimPower ("Rim Power", Range(0,8.0)) = 3.0
_ReflectColor ("Reflection Color", Color) = (1,1,1,0.5)
[NoScaleOffset] _Cube ("Cubemap", CUBE) = "" {}
}
SubShader {
CGPROGRAM
#pragma surface surf BlinnPhong
struct Input {
float3 worldRefl;
float3 viewDir;
};
samplerCUBE _Cube;
fixed4 _Color;
fixed4 _ReflectColor;
half _Shininess;
half _RimPower;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = _Color.rgb;
o.Gloss = _Color.a;
o.Specular = _Shininess;
half rim = saturate(dot (normalize(IN.viewDir), o.Normal));
o.Emission = texCUBE (_Cube, IN.worldRefl).rgb * _ReflectColor.rgb * pow(rim,_RimPower);;
}
ENDCG
}
FallBack "Mobile/Diffuse"
}
上面的着色器代码是下图左侧的红色宝石:
我的目标是看起来与右边的宝石相似。我一路上遇到了一些挑战。左边的宝石是不透明的,可以接受阴影。右边的宝石有正面透明但不是背面。然而,这不接受阴影。我不得不在BlinnPhong上制作宝石,这样它就可以投射和接收阴影。
是否可以为正面和背面透明度创建不同的控件?还有一种方法可以让透明物体接受阴影吗?我想为宝石添加轮廓,以便可以看到更远的地方。有没有办法在同一通行证中添加轮廓,还是必须有自己独立的通行证?另外,你怎么能让收到的阴影变暗?是否所有这些要求都要归功于GPU?该游戏适用于移动平台。
我是CG编程的初学者。我的第一步是弄清楚转换表面编程到顶点/片段。任何例子都会非常感激。
我确实在资产商店购买了几个宝石资产,但其中一些可以投下阴影,但根本无法接收或无法投射或接收。是什么赋予了?右侧的宝石着色器来自资产商店购买的资产之一。我不想在未经他们许可的情况下在本网站上分享他们的着色器脚本。
答案 0 :(得分:0)
这实际上是一个相当复杂的过程,尽管我建议您首先从其网站下载unity shader源代码。大多数实际阴影是在UnityStandardBRDF.cginc,UnityPBSLighting.cginc和UnityStandardCore.cginc中完成的。如果您对它们进行搜索,也可以在github上找到这些文件。
基本上,前向着色器的基本结构如下:
Shader "MyForwardAddShader"
{
Properties
{
_MainTex("Some texture", 2D) = "white"{}
}
SubShader
{
Tags {"RenderType"="Geometry" "Queue" = "Geometry"}
Pass
{
// Forward Base pass - this applies main directional light and ambient
Name "FORWARD"
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma target 3.5
#pragma multi_compile_fwdbase
#pragma multi_compile_fog
#pragma multi_compile_instancing
#pragma vertex vert
#pragma fragment frag
// I Like to keep these in separate include files
#include "MyForwardBase.cginc"
ENDCG
}
Pass
{
// Forward Add pass - this is added once per extra light source
Name "FORWARD_DELTA"
Tags { "LightMode" = "ForwardAdd" }
Blend SrcAlpha One
Fog { Color (0,0,0,0) } // in additive pass fog should be black
ZWrite Off
ZTest LEqual
CGPROGRAM
#pragma target 3.5
#pragma multi_compile_fwdadd_fullshadows
#pragma multi_compile_fog
#pragma vertex vert
#pragma fragment frag
#include "MyForwardAdd.cginc"
ENDCG
}
}
}
请注意,您还需要一个阴影投射器通行证来投射阴影(您可以只复制标准着色器源代码中使用的通行证),如果要使用烘焙的照明,还需要一个元通行证。
类似“ MyForwardBase.cginc”的文件应包括顶点输入和输出结构的定义,以及传递过程的顶点和片段功能。使用此设置,您还需要在此处定义制服(属性变量)。光照计算可能需要一些变量:
// Calculate this in the vertex shader and normalize per fragment
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
float3 viewDir = _WorldSpaceCameraPos.xyz - o.worldPos;
// In the ForwardBase pass, _WorldSPaceLightPos0.xyz stores the direction of the main directional light, instead of position.
// Use this in the vertex function:
half3 mainLightColor = _LightColor0.rgb;
half3 mainLightDir = _WorldSpaceLightPos0.xyz;
对于ForwardBase传递,您需要包括“ AutoLight.cginc”,并在顶点函数中使用此宏:
COMPUTE_LIGHT_COORDS(o);
这又需要您在VertexOutput结构中包含此宏:
UNITY_LIGHTING_COORDS(6,7) // 6, 7 can be any texture interpolator IDs, they will translate to TEXCOORD6 and TEXCOORD7 in this case
ForwardAdd光衰减的工作原理如下:
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos.xyz); // Here, worldPos is stored in the vertex output struct and calculated per vertex
half3 lightColor = _LightColor0.rgb * atten;
还有一些宏可以找出像素是否在阴影中,您可以在AutoLight.cginc中找到它们。在ForwardAdd通道中,按每个顶点的方向计算光照方向,如下所示:
o.lightDir = _WorldSpaceLightPos0.xyz - o.worldPos.xyz * _WorldSpaceLightPos0.w;
我个人而言,我喜欢为每个功能(例如反射,折射,三边形贴图等)创建小的CGIncludes,并在需要时将它们包括在内。我还倾向于在其自己的包含文件中保留一个单独的名为“ Lighting”的函数,因为光照计算在各遍之间共享。此函数将所有变量(如lightDir,viewDir,反照率,粗糙度等)用作参数,并返回片段的阴影颜色。
就像我说的那样,这是一个非常复杂的过程,这只是入门。实施照明功能本身就是一个故事,尽管查看UnityStandardBRDF.cginc可以帮助实现这一点。我建议您从基本的blinn-phong模型开始进行调试,然后从那里进行改进。