首页 > 解决方案 > 着色器在 Unity 编辑器中工作正常,但在 WebGL 构建中变黑

问题描述

我正在开展一个项目,该项目将不同位置的传感器值编码为建筑物的 3d 热图。我为此使用了顶点着色器,这在 Editor: example中工作得很好,但是在我在 WebGL 中构建场景之后,结果是黑色的。

我尝试过使用常量循环索引或始终在项目设置等中包含此着色器,但这些都不起作用。以下是一些代码:

                v2f vert(appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
                    o.screenPos = ComputeScreenPos(o.vertex);
                    UNITY_TRANSFER_FOG(o,o.vertex);
                    return o;
                }
//...
                float2 boxIntersection(in float3 ro, in float3 rd, in float3 rad)
                {
                    float3 m = 1.0 / rd;
                    float3 n = m * ro;
                    float3 k = abs(m) * rad;
                    float3 t1 = -n - k;
                    float3 t2 = -n + k;

                    float tN = max(max(t1.x, t1.y), t1.z);
                    float tF = min(min(t2.x, t2.y), t2.z);

                    if (tN > tF || tF < 0.0) return float2(-1.0, -1.0); // no intersection

                    return float2(tN, tF);
                }

                //p in object space
                float SampleValue(float3 p) {
                    float totalValue = 0.0;
                    float denom = 0.0;

                    for (int i = 0; i < 34; ++i) {   // _DataSize
                        float4 sd = _SensorData[i];
                        float dist = length(p - sd.xyz);

                        totalValue += sd.w / (dist * dist);
                        denom += 1.0 / (dist * dist);
                    }

                    if (denom == 0.0) {
                        return 0.0;
                    }

                    return totalValue / denom;
                }

                float4 transferFunction(float value) {
                    float tv = (value - _DataScale.x) / (_DataScale.y - _DataScale.x);   // _DataScale.x, _DataScale.y

                    float4 col = tex2D(_TransferTexture, float2(0.5, tv));
                    col.w *= _Strength;     // _Strength
                    return float4(col.xyz * col.w, col.w);
                }

                float4 rayMarch(float3 ro, float3 rd, float dp) {
                    float3 ro1 = mul(unity_WorldToObject, float4(ro, 1.0));
                    float3 rd1 = mul(unity_WorldToObject, rd);

                    float2 t = boxIntersection(ro1, rd1, float3(1, 1, 1) * 0.5);
                    t.x = length(mul(unity_ObjectToWorld, float4(ro1 + rd1 * max(t.x, 0.0), 1.0)) - ro);
                    t.y = length(mul(unity_ObjectToWorld, float4(ro1 + rd1 * t.y, 1.0)) - ro);
                    t.y = min(t.y, dp);

                    float4 acc = float4(0.0, 0.0, 0.0, 1.0);

                    float totalDelta = (t.y - t.x);
                    float delta = totalDelta / float(_RM_Samples - 1.0);

                    float3 p = ro + t.x * rd;

                    for (int i = 0; i < 34; ++i) {   // _RM_Samples
                        float v = SampleValue(p);

                        float4 tf = transferFunction(v);

                    float tr = exp(-tf.w * delta);

                    acc.xyz += tf.xyz * acc.w * delta;
                    acc.w *= tr;

                    p += delta * rd;
                    }

                    return float4(acc.xyz, (1.0 - acc.w) * step(t.x, t.y));
                }

            fixed4 frag(v2f i) : SV_Target
            {
                float2 tc = i.screenPos.xy / i.screenPos.w;
                float depth = UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, tc));
                float eD = LinearEyeDepth(depth);

                float3 ro = _WorldSpaceCameraPos;
                float3 rd = normalize(i.worldPos - ro);

                float4 col = rayMarch(ro, rd, eD);
                //if (col.w < 1) col = float4(1, 0, 0, 1); 
                //else col = float4(0, 1, 0, 1);
                if (wingCullPlaneValue(i.worldPos.xyz) == 0 || cullPlaneValue(i.worldPos.xyz) == 0) {
                    discard;
                }

                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }


由于这在编辑器中运行良好,我认为没有任何错误boxIntersectionrayMarching功能。我想知道 WebGl 中是否有什么特别之处,它以不同的方式处理像素,我必须相应地调整一些代码。我是 WebGL 和 Shader 的新手,如果有任何帮助或建议,我将不胜感激,在此先感谢。

标签: unity3dshaderunity-webgl

解决方案


那是因为阶跃函数。用你自己的 sigmoid 函数来近似它(可能很昂贵)

float emulated_step(float a, float x){
    return 1.0/(1+pow(1000, -(x-a)*8192));
}

推荐阅读