How to get multiple values from a texture in parallel in HLSL (ShaderLab)?

142 Views Asked by At

I am new to HLSL (ShaderLab) and this site. I need some help.

Shader "TEST/UnlitMultiStarTest"
{
    Properties
    {
        _BaseColor("BaseColor", Color) = (0, 0, 0, 1)
        _StarColor("StarColor", Color) = (1, 1, 1, 1)
        _StarStrength("StarStrength", Float) = 100
        _Pos("Star Potisions Texture", 2D) = "White" {}
    }
    SubShader
    {
        Tags { "RenderType"="BackGround" "Queue"="BackGround+0"}
        Cull OFF
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 coord0 : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 eyeDir : TEXCOORD2;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            uniform float4 _StarColor;
            uniform float _StarStrength;
            uniform float4 _BaseColor;
            sampler2D _Pos;
            float3 _Pos_TexelSize;

            float2 decodetex(float2 uv, uint a, uint b){
                float NtexSize = _Pos_TexelSize.x;
                float e = NtexSize/2;
                float4 pos4 = tex2Dlod(_Pos, float4(float2(NtexSize*a +e, NtexSize*b +e), 0,0));
                float2 pos2 = float2((pos4.g*90 -45)*2, (pos4.r*360));
                return pos2;
            }

            float3 PolarToCartesian(float2 pd)
            {
                return float3 (sin(pd.y)*cos(pd.x), sin(pd.x), cos(pd.x)*cos(pd.y));
            }

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.coord0;
                o.eyeDir = UnityWorldSpaceViewDir(mul(unity_ObjectToWorld, v.vertex).xyz);
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = _BaseColor;
                float texWidth = _Pos_TexelSize.z;
                for (uint a = 0; a<4; a++){
                    for (uint b = 0; b<4; b++){
                        float2 StarDir = decodetex(i.uv,a,b);
                        float3 StarPos = normalize(PolarToCartesian(float2(radians(StarDir.x), radians(StarDir.y))));
                        float4 StarOut = mul( step(0.999, pow( max( dot(StarPos, mul(normalize(i.eyeDir), -1)),0),_StarStrength)),_StarColor);
                        col += StarOut;
                    }
                }
                return col;
            }
            ENDCG
        }
    }
}

This shader gets the numbers from a Pos texture with spherical coordinates written into the rg values and draws the stars at infinity. Right now I am using 16 of them in a 4*4 texture for testing. However, I would like to eventually draw a large number of stars like in a planetarium, but using a for loop makes it very computationally infeasible. Is there any way to get the position of each star from the texture without using a for loop?

I tried simply passing the uv value as an argument to the decodetex function, but only one point was drawn.

            float2 decodetex(float2 uv){
                float4 pos4 = tex2Dlod(_Pos, float4(uv, 0,0));
                float2 pos2 = float2((pos4.g*90 -45)*2, (pos4.r*360));
                return pos2;
            }

Postscript. I found the cause of the problem. It seems that when using a 4*4 texture, for example, the celestial uv is divided into 16 cells of that pixel count, and points are drawn only if there is a point read from the corresponding pixel in that cell. The shader on the left is the shader using the code in the question text, and the shader on the right is the shader using the uv coordinates as is for decoding. Some of the points are drawn at the same position, and some are interrupted at the cell boundaries.

1 2

0

There are 0 best solutions below