1
\$\begingroup\$

I'm trying to create a shader that takes a grayscale map as input, and returns a colored albedo that I want to use as texture for my PCG planets, I think that the code below should work, but it only produces flatly white objects.

I'm a total shader noob, so I'm terribly sorry if I'm missing something obvious here.

    Shader "Custom/Planet" {
    Properties{
        _height("HeightMap", 2D) = "white" {}
    }
    SubShader{
        Tags { "RenderType" = "Opaque" }
        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        struct Input {
            float2 _heightMap;
        };

        float minHeight = 0;
        float maxHeight = 1;

        float inverseLerp(float a, float b, float v) {
            return saturate((v - a) / (b - a));
        }

        //UNITY_INSTANCING_CBUFFER_START(Props)
        //UNITY_INSTANCING_CBUFFER_END

        void surf (Input IN, inout SurfaceOutputStandard o) {
            float hv = inverseLerp(minHeight, maxHeight, IN._heightMap);
            o.Albedo = hv;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
\$\endgroup\$
  • \$\begingroup\$ change your Input to uv_heightMap and inverseLerp(minHeight, maxHeight,IN.uv_heightMap); if you need color you should have float4 in Albedo \$\endgroup\$ – Seyed Morteza Kamali Jan 27 '18 at 16:26
  • \$\begingroup\$ How do you want to map the grayscale heightmap to colours? What should black / medium grey / white map to? \$\endgroup\$ – DMGregory Jan 27 '18 at 18:06
  • \$\begingroup\$ @DMGregory I'd ideally like to be able to at runtime set a range of colors as input in the material, and then have the shader blend the values depending on the value of the heightmap (everything < .5f = Color x, etc, etc). \$\endgroup\$ – ag4w Jan 28 '18 at 2:26
  • \$\begingroup\$ How do you intend to express those colour mappings at runtime? As a set of colour properties and cutoff values as parameters to the material? Or as a texture gradient ramp? Or something else? \$\endgroup\$ – DMGregory Jan 28 '18 at 3:00
  • \$\begingroup\$ @DMGregory I intend to express them as a texture gradient map later on, but I'd be happy with colors (float4s, really) for now. \$\endgroup\$ – ag4w Jan 28 '18 at 11:47
0
\$\begingroup\$

You've probably already figured it out, but just in case. If you want to remap your height values to the colours from the texture gradient, this should do the job:

void surf (Input IN, inout SurfaceOutputStandard o) { // map height to [0, 1] values float hv = inverseLerp(minHeight, maxHeight, IN._heightMap); // create UV from height float2 uv = float2(hv, 0.0); // sample gradient texture o.Albedo = tex2D(_GradientTexture, uv); }

Note that I used 2D texture for gradient, but you can use 1D texture instead, or use 2D texture and pack different gradients, then u-coordinate will be as usual (normalized height value), and v-coordinate can select graient type. E.g.

int planet_type = ...; // from 0 to textue_height-1

// this math is used so vertical coordinate will fall exactly at the pixel center, so 2 horizontal gradient lines will not be mixed if you are using bilinear filtering to sample _GradientTexture int v = 0.5/textue_height + (float)planet_type/textue_height;

o.Albedo = tex2D(_GradientTexture, float2(u, v));

Beside the color you can alse generate normals from height map to get more details for lighting, you can look e.g. here or here. Take care about different scale values for height(Z) and XY

\$\endgroup\$
0
\$\begingroup\$

To Creating color texture from grayscale you can use HSL or HSV color.

HSL (Hue, Saturation, Lightness) and HSV (Hue, Saturation, Value) are two alternative representations of the RGB color model, designed in the 1970s by computer graphics researchers to more closely align with the way human vision perceives color-making attributes. https://en.wikipedia.org/wiki/HSL_and_HSV

Shader "Smkgames/HSBC" {
    Properties {
        _MainTex ("Texture", 2D) = "white" {}
        _Hue ("Hue", Range(0, 1.0)) = 0
        _Saturation ("Saturation", Range(0, 1.0)) = 0.5
        _Brightness ("Brightness", Range(0, 1.0)) = 0.5
        _Contrast ("Contrast", Range(0, 1.0)) = 0.5
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows

        #pragma target 3.0

        sampler2D _MainTex;
        fixed _Hue, _Saturation, _Brightness, _Contrast;
        float4 _Color;

        struct Input {
            float2 uv_MainTex;
        };

        inline float3 applyHue(float3 aColor, float aHue)
            {
                float angle = radians(aHue);
                float3 k = float3(0.57735, 0.57735, 0.57735);
                float cosAngle = cos(angle);

                return aColor * cosAngle + cross(k, aColor) * sin(angle) + k * dot(k, aColor) * (1 - cosAngle);
            }

            inline float4 applyHSBCEffect(float4 startColor, fixed4 hsbc)
            {
                float hue = 360 * hsbc.r;
                float saturation = hsbc.g * 2;
                float brightness = hsbc.b * 2 - 1;
                float contrast = hsbc.a * 2;

                float4 outputColor = startColor;
                outputColor.rgb = applyHue(outputColor.rgb, hue);
                outputColor.rgb = (outputColor.rgb - 0.5f) * contrast + 0.5f;
                outputColor.rgb = outputColor.rgb + brightness;
                float3 intensity = dot(outputColor.rgb, float3(0.39, 0.59, 0.11));
                outputColor.rgb = lerp(intensity, outputColor.rgb, saturation);

                return outputColor;
            }



        UNITY_INSTANCING_CBUFFER_START(Props)
        UNITY_INSTANCING_CBUFFER_END



        void surf (Input IN, inout SurfaceOutputStandard o) {
            fixed4 startColor = 1-tex2D(_MainTex, IN.uv_MainTex) + float4(1,0,0,1);     
            float4 hsbc = fixed4(_Hue, _Saturation, _Brightness, _Contrast);        
            float4 hsbcColor = applyHSBCEffect(startColor, hsbc);

            o.Albedo = hsbcColor;
        }
        ENDCG
    }
    FallBack "Diffuse"
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.