首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >接收和投下阴影(自定义几何草阴影)-统一C#

接收和投下阴影(自定义几何草阴影)-统一C#
EN

Stack Overflow用户
提问于 2018-01-10 19:46:39
回答 1查看 6.1K关注 0票数 1

我在听山姆·沃伦斯基的教程。零世界(零世界教程),他为一个点云草发生器编写了一个几何着色器。伟大的教程,但我想知道(并没有找到一个适当的解决方案,经过几天的研究),我如何能够实现阴影的着色器(投射和接收阴影)。我试图挖掘更深的阴影,但这是一个很高的水平,对我来说。

我的问题是:如何为这个草着色器实现阴影投射和接收?到目前为止存在并运行良好的代码如下:

代码语言:javascript
复制
Shader "Custom/GrassGeometryShader" {

    // https://www.youtube.com/watch?v=HY6qFbmbij8 und http://www.battlemaze.com/?p=153

    Properties {
    // --> HDR allows High Dynamic Colors
        [HDR]_BackgroundColor ("Background Color", Color) = (1,0,0,1) // default to red
        [HDR]_ForegroundColor ("Foreground Color", Color) = (0,1,0,1) // default to green 
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
        _Cutoff("Alpha Cuttoff", Range (0,1)) = 0.15 // Wieviel abgeschnitten sien soll
        _GrassHeight("GrasHeight", Float) = 0.25
        _GrassWidt("GrasWidth", Float) = 0.25
        _WindSpeed ("WindSpeed", Float) = 100
        _WindStrength("WindStrength", Float) = 0.05
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        Pass
        {

        Cull OFF 
        CGPROGRAM
        #include "UnityCG.cginc" // like: "using" in C# 
        // Vertex-Shader with vert-function
        #pragma vertex vert
        // Fragment-Shader with frag-function
        #pragma fragment frag
        // Geometry-Shader with geom-function 
        #pragma geometry geom

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 4.0 // needs to be 4.0 !

        sampler2D _MainTex;

        // vertex to graphics (v2g)
        struct v2g 
        {
            float4  pos : SV_POSITION;
            float3  norm : NORMAL;
            float2  uv : TEXCOORD0;
            float3 color : TEXCOORD1;
        };

        //graphics to fragments (g2f)
        struct g2f 
        {
            float4  pos : SV_POSITION;
            float3  norm : NORMAL;
            float2  uv : TEXCOORD0;            
            float3 diffuseColor : TEXCOORD1;
            //float3 specularColor : TEXCOORD2;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _BackgroundColor;
        fixed4 _ForegroundColor;
        half _GrassHeight;
        half _GrassWidth;
        half _Cutoff;
        half _WindStrength;
        half _WindSpeed;

        // Vertex-Shader from Battlemaze.com
        v2g vert(appdata_full v)
        {
            float3 v0 = mul(unity_ObjectToWorld, v.vertex).xyz;

            v2g OUT;
            OUT.pos = v.vertex;
            OUT.norm = v.normal;
            OUT.uv = v.texcoord;
            OUT.color = tex2Dlod(_MainTex, v.texcoord).rgb;
            return OUT;         
        }

        void buldQuad(inout TriangleStream<g2f> triStream, float3 points[4], float3 color) {
            g2f OUT;
            float3 faceNormal = cross(points[1]-points[0], points[2]-points[0]);
            for(int i; i < 4; ++i) {
            OUT.pos = UnityObjectToClipPos(points[i]);
            OUT.norm = faceNormal;
            OUT.diffuseColor = color;
            OUT.uv = float2(i%2, (int)i/2);
            triStream.Append(OUT);
            }
            triStream.RestartStrip();
        }

        // geom-Funktion
        [maxvertexcount(24)]
        void geom(point v2g IN[1], inout TriangleStream<g2f> triStream)
        {
            float3 lightPosition = _WorldSpaceLightPos0;

            float3 perpendicularAngle = float3(0,0,1);
            float3 faceNormal = cross(perpendicularAngle, IN[0].norm); // normal of gras

            float3 v0 = IN[0].pos.xyz; // Tip of the gras
            float3 v1 = IN[0].pos.xyz + IN[0].norm * _GrassHeight; // base of the gras
            float3 v2 = IN[0].pos.xyz + IN[0].norm * _GrassHeight / 2; // middle part (?)

            float3 wind = float3(sin(_Time.x * _WindSpeed + v0.x) + sin(_Time.x * _WindSpeed + v0.z * 2), 0, cos(_Time.x * _WindSpeed + v0.x * 2) + cos(_Time.x * _WindSpeed + v0.z)); // Anzahl oder Stärke der Manipulation an den Eckpunkten 
            // (_Time.x + v0.x + v0.z looks "random", because it's using time + coordinates)

            v1 += wind * _WindStrength;
            v2 += (wind * _WindStrength/2)/2;

            float3 color = (IN[0].color); // color of the gras

            float sin30 = 0.5;
            float sin60 = 0.866f;
            float cos30 = sin60;
            float cos60 = sin30;

            g2f OUT;

            // Quad 1 - the following code could fit in one function (BUT!) it did not work on MacOSX, that's why it's still calculated the long way

        OUT.pos = UnityObjectToClipPos(v0 + perpendicularAngle * 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(1, 0);
        triStream.Append(OUT);


        OUT.pos = UnityObjectToClipPos(v1 + perpendicularAngle * 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(1, 1);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v0);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 1);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1 - perpendicularAngle * 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0, 1);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v0 - perpendicularAngle * 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v0);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 1);
        triStream.Append(OUT);

        // Quad 2

        OUT.pos = UnityObjectToClipPos(v0 + float3(sin60, 0, -cos60) * 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(1, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1 + float3(sin60, 0, -cos60)* 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(1, 1);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v0);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 1);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v0 - float3(sin60, 0, -cos60) * 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1 - float3(sin60, 0, -cos60) * 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0, 1);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v0);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 1);
        triStream.Append(OUT);

        // Quad 3 - Positive

        OUT.pos = UnityObjectToClipPos(v0 + float3(sin60, 0, cos60) * 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(1, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1 + float3(sin60, 0, cos60)* 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(1, 1);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v0);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 1);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v0 - float3(sin60, 0, cos60) * 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1 - float3(sin60, 0, cos60) * 0.5 * _GrassHeight);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0, 1);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v0);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 0);
        triStream.Append(OUT);

        OUT.pos = UnityObjectToClipPos(v1);
        OUT.norm = faceNormal;
        OUT.diffuseColor = color;
        OUT.uv = float2(0.5, 1);
        triStream.Append(OUT);

        }

        // Fragment-Shader by Battlemaze.com --> gets input v2g and renders it on screen
        half4 frag(g2f IN) : COLOR
        {
            fixed4 c = tex2D(_MainTex, IN.uv);
            clip(c.a - _Cutoff);
            return c;
            //return float4 (IN.diffuseColor.rgb, 1.0);
        }

        ENDCG
        }
    }
}

正如我提到的,我使用的是一台运行MacOS的机器,不幸的是,这台机器不能处理计算机着色器。

我希望能在这方面提供任何帮助。

EN

回答 1

Stack Overflow用户

发布于 2019-03-14 19:41:48

添加对阴影接收的支持

在CGPROGRAM块的顶部添加以下内容:

代码语言:javascript
复制
#include "AutoLight.cginc"

还可能需要添加以下内容:

代码语言:javascript
复制
#pragma multi_compile_fwdbase

在您的g2f结构中,添加以下行:

代码语言:javascript
复制
SHADOW_COORDS(3) // (3) means we are using TEXCOORD3

在您的几何图形着色器中,对于每个新的顶点,在分配OUT.pos之后添加这一行:

代码语言:javascript
复制
TRANSFER_SHADOW(OUT)

最后,在片段函数中添加以下内容:

代码语言:javascript
复制
half shadow = SHADOW_ATTENUATION(IN)

现在,“阴影”变量包含您的阴影掩码。在一个有光的着色器里,你会用浅色把它乘以,但在你的例子中,你可以用输出反照率来乘以它。

添加对阴影投射的支持

将下列传递添加到您的着色器:

代码语言:javascript
复制
Pass {
    Name "ShadowCaster"
    Tags { "LightMode" = "ShadowCaster" }

    ZWrite On ZTest LEqual

    CGPROGRAM
    #pragma target 2.0

    #pragma multi_compile_shadowcaster

    #pragma vertex vertShadowCaster
    #pragma fragment fragShadowCaster

    #include "UnityStandardShadow.cginc"

    ENDCG
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48194981

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档