Interpretation of the Shader Series 8 Written by CG in Unity-Multi-light source diffuse reflection and unityshader
In the previous article, the simplest shader is only the diffuse reflection under a single light source, but often there is not only one light source in the scenario, so how can the diffuse reflection intensity of the surface of our objects be combined when multiple light sources exist? What does the tag "LightMode" = "ForwardBase" mentioned above mean?
The built-in DiffuseShader of Unity, that is, when we create a Material, the default Shader is also multi-light source. Therefore, the shader completed in this article is basically consistent with the default diffuse shader.
First introduce several concepts
The Rendering path Rendering PathUnity provides three modes for processing multiple light sources:
Edit -- Project Settings -- Player -- Other Settings -- Rendering Path1. vertex Lit2. direction Forward (default) 3. delayed Lighting Deferred Lighting our shader also uses the default Forward Pixel light Pixel LightUnity to call the parallel light as the Pixel light. The first Pixel light is the basic parallel light and is decorated with the LightMode = ForwardBase label, each pixel is decorated with the LightMode = ForwardAdd label. Not all light sources are reflected to objects at runtime, but are rendered based on the number of pixels set in Project Quality.
The default Pixel Light quantity should be 2. If we have more parallel Light on the object, we need to adjust the number of Pixel Light in Edit> Project Settings> Quality, for example:
When the actual number of pixels in a scenario exceeds the set value, unity only renders the most important light. We will continue to discuss how to change the rendering mode of the light source to important and unimportant.
On the Principle of pixel light superposition, we have already mentioned in Series 6 that the fragment shader is to calculate the information transmitted by the mesh component as color (or depth) and store it in the Frame Buffer). The color output between each Pass is mixed by a certain formula.
Here we use the one-to-one mode for color mixing, that is, the mixing command is:
Blend One One
The code for the second Pass can also directly copy the first Pass. Change LightMode = ForwardBase In the Tags label to LightMode = ForwardAdd.
Code
Shader "Custom/Multi-Light Diffuse" {Properties {// The default Material Color is black. You can adjust _ Color ("Material Color", Color) = (1, 1, 1, 1)} SubShader {Pass {// The reflection channel of the first pixel light is marked as ForwardBaseTags {"LightMode" = "ForwardBase"} CGPROGRAM/Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs. // # pragma exclude_renderers gles // defines the vertex shader and fragment shader entry # pragma vertex vert # pragma fragment frag // gets the Material Color uniform float4 _ Color defined in property; // position or direction of the light source // uniform float4 _ WorldSpaceLightPos0; // The color of the light source (from "Lighting. cginc ") uniform float4 _ LightColor0; // defines the input parameter struct of the vertex shader. // We only need the POSITION of each vertex and the corresponding normal vector struct vertexInput {float4 vertex: POSITION; float3 normal: NORMAL;}; // defines the output struct of vertex coloring/the input struct of fragment coloring // The calculated color struct vertexOutput {float4 pos: SV_POSITION; float4 col: COLOR ;}; // vertexOutput vert (vertexInput input) {vertexOutput output; // transformation matrix from the object coordinate system to the world coordinate system // _ Object2World and _ World2Object are built-in uniform parameter float4x4 modelMatrix = _ Object2World provided by unity; // The transformation matrix float4x4 modelMatrixInverse = _ World2Object from the world coordinate system to the object coordinate system; // calculate the unit vector of the vertex normal vector in the object coordinate system // multiply the vertex normal vector transmitted from the mesh with the model --> the object coordinate system matrix to obtain the normal vector in the object coordinate system // then unitization float3 normalDirection = normalize (float3 (mul (float4 (input. normal, 0.0), modelMatrixInverse); // calculates the unit vector float3 lightDirection = normalize (float3 (_ WorldSpaceLightPos0) of the incident vector )); // calculate the color after reflection. // first multiply the color of the light source and the color vector of the material. // then multiply the max (0, cos cosine (N, L) mentioned above )) float3 diffuseReflection = float3 (_ LightColor0) * float3 (_ Color) * max (0.0, dot (normalDirection, lightDirection); // The above calculated is an RGB Color with A difference, after adding one dimension, you can pass it to the clip coloring tool output. col = float4 (diffuseReflection, 1); // International Convention, three-step curve of vertex change. In this example, output can be written or not. pos = mul (UNITY_MATRIX_MVP, input. vertex); return output;} // fragment shader, which uses the output parameter of the vertex shader as the input parameter float4 frag (vertexOutput input) of the fragment shader ): COLOR {return input. col ;} ENDCG} Pass {// The reflection channel of the remaining pixel light is marked as ForwardAddTags {"LightMode" = "ForwardAdd"} // when the clip color of this channel is output, the frame cache has with color, therefore, the hybrid mode must be 1 to 1 Blend One OneCGPROGRAM // Upgrade NOTE: excluded shader from OpenGL ES 2.0 because it does not contain a surface program or both vertex and fragment programs. // # pragma exclude_renderers gles // defines the vertex shader and fragment shader entry # pragma vertex vert # pragma fragment frag // gets the Material Color uniform float4 _ Color defined in property; // position or direction of the light source // uniform float4 _ WorldSpaceLightPos0; // The color of the light source (from "Lighting. cginc ") uniform float4 _ LightColor0; // defines the input parameter struct of the vertex shader. // We only need the POSITION of each vertex and the corresponding normal vector struct vertexInput {float4 vertex: POSITION; float3 normal: NORMAL;}; // defines the output struct of vertex coloring/the input struct of fragment coloring // The calculated color struct vertexOutput {float4 pos: SV_POSITION; float4 col: COLOR ;}; // vertexOutput vert (vertexInput input) {vertexOutput output; // transformation matrix from the object coordinate system to the world coordinate system // _ Object2World and _ World2Object are built-in uniform parameter float4x4 modelMatrix = _ Object2World provided by unity; // The transformation matrix float4x4 modelMatrixInverse = _ World2Object from the world coordinate system to the object coordinate system; // calculate the unit vector of the vertex normal vector in the object coordinate system // multiply the vertex normal vector transmitted from the mesh with the model --> the object coordinate system matrix to obtain the normal vector in the object coordinate system // then unitization float3 normalDirection = normalize (float3 (mul (float4 (input. normal, 0.0), modelMatrixInverse); // calculates the unit vector float3 lightDirection = normalize (float3 (_ WorldSpaceLightPos0) of the incident vector )); // calculate the color after reflection. // first multiply the color of the light source and the color vector of the material. // then multiply the max (0, cos cosine (N, L) mentioned above )) float3 diffuseReflection = float3 (_ LightColor0) * float3 (_ Color) * max (0.0, dot (normalDirection, lightDirection); // The above calculated is an RGB Color with A difference, after adding one dimension, you can pass it to the clip coloring tool output. col = float4 (diffuseReflection, 1); // International Convention, three-step curve of vertex change. In this example, output can be written or not. pos = mul (UNITY_MATRIX_MVP, input. vertex); return output;} // fragment shader, which uses the output parameter of the vertex shader as the input parameter float4 frag (vertexOutput input) of the fragment shader ): COLOR {return input. col;} ENDCG }}}
In this way, we can see the effect of the two light sources after adding the second light source. Here we reserve the single light source diffuse reflection shader in the previous example to compare the effect, and then create two spheres respectively, set two light sources in the scenario to see The comparison results:
We can see that in the same scenario, two parallel lights are shining on two sphere. One reflects only the diffuse reflection of the main light source (ForwardBase), and the other combines the diffuse reflection of the two parallel lights.
If a parallel Light is added to the scenario, we can add a Pass mark as ForwardAdd and adjust Pixcel Light Count to 3 in Quality.
What SHADER is used for ao pasters in unity3d?
If you have done a good job of AO, you can use diffuse to check the effect.