Author Topic: Custom Shader  (Read 791 times)

Mike O'Donnell

  • Guest
Custom Shader
« on: July 19, 2019, 08:25:00 AM »
So, I'm trying to make my own custom shader so I can use some higher resolution images with the globe. I honestly don't know much about graphics programming, so I'm using the WPM shaders as a reference. This code that you have,
Code
if (i.uv.x<0.5) {
if (i.uv.y>0.5) {
color = tex2Dlod(_TexTL, float4(i.uv.x * 2.0, (i.uv.y - 0.5) * 2.0, 0, 0));
} else {
color = tex2Dlod(_TexBL, float4(i.uv.x * 2.0, i.uv.y * 2.0, 0, 0));
}
} else {
if (i.uv.y>0.5) {
color = tex2Dlod(_TexTR, float4((i.uv.x - 0.5) * 2.0f, (i.uv.y - 0.5) * 2.0, 0, 0));
} else {
color = tex2Dlod(_TexBR, float4((i.uv.x - 0.5) * 2.0f, i.uv.y * 2.0, 0, 0));
}
}                                 

utilizes four separate textures to, TR, TL, BR, BL, to cover the earth evenly. How would I modify the code/math in order to use eight separate textures instead?

Thanks,
Mike

Kronnect

  • Administrator
  • Hero Member
  • *****
  • Posts: 5320
    • View Profile
Re: Custom Shader
« Reply #1 on: July 19, 2019, 10:14:35 AM »
Hi Mike,

The i.uv field represents the texture coordinates (i.uv.xy are x and y in the texture, or i.uv.x and i.uv.y). These coordinates are expressed in 0-1 range. So 0.5 is half the texture.
To add more textures you could add more "if" clauses, each one checking if the given i.uv are withing the proper patch region (0-0.25, 0.25-0.5 and so on, for both x and y).

tex2Dlod is a GLSL/HLSL function that reads or samples the texture at the given coordinate.
In this case, tex2Dlod uses 4 parameters (a float4). The first 2 values are the xy. The others can be left to 0.
You can read more details on the NVIDIA reference: https://developer.download.nvidia.com/cg/tex2Dlod.html

Regards

Mike O'Donnell

  • Guest
Re: Custom Shader
« Reply #2 on: July 19, 2019, 10:39:25 AM »
Can you go into more detail as to why, in the tex2Dlod function, you sometimes multiply the uv.x or uv.y values by 2.0, and sometimes you subtract 0.5 first? I don't quite get the significance of these values and when to mix them around.

Kronnect

  • Administrator
  • Hero Member
  • *****
  • Posts: 5320
    • View Profile
Re: Custom Shader
« Reply #3 on: July 19, 2019, 10:57:42 AM »
Imagine a quad subdivided in 4 tiles. Those calculations map the 0..1 range given to the fragment shader into the 0..1 range of each individual texture.
For example:

Code
if (i.uv.x<0.5) {
if (i.uv.y>0.5) {
color = tex2Dlod(_TexTL, float4(i.uv.x * 2.0, (i.uv.y - 0.5) * 2.0, 0, 0));
..

This "if" checks if the uv coordinates corresponds to the Top/Left tile (x = 0-0.5 and y=0.5-1.0). Then it multiplies those values so it maps to the 0..1 range of the texture. So the 0,0 coordinate of the texture corresponds to the 0,0.5 position of the quad. And the 1,1 coordinate of the texture corresponds to the 0.5,1.0 coordinate of the quad.

For the top/left tile, the basically is applying this formula:
texture_X = tile_X * 2.0
texture_Y = (tile_Y - 0.5) * 2.0


« Last Edit: July 19, 2019, 10:59:22 AM by Kronnect »

Mike O'Donnell

  • Guest
Re: Custom Shader
« Reply #4 on: July 19, 2019, 11:51:15 AM »
Alright, I think I have each texture lined up on the globe properly. Though for some reason, it looks like each texture is too big for their individual section, so each texture is cut off before it gets to the next texture. Would this also be a UV issue?


Kronnect

  • Administrator
  • Hero Member
  • *****
  • Posts: 5320
    • View Profile
Re: Custom Shader
« Reply #5 on: July 19, 2019, 11:54:40 AM »
Not sure. Can you send me a copy of the project?

Mike O'Donnell

  • Guest
Re: Custom Shader
« Reply #6 on: July 22, 2019, 06:26:06 AM »
Hey, sorry. I didn't see this reply until the end of the workday, so I didn't have time to respond. I don't think the whole project is necessary, the error is most likely in my shader code.

Code
Shader "Unlit/TRUE_EARTH"
{
    Properties
    {
        _TexA1 ("Tex A1", 2D) = "white" {}
_TexA2 ("Tex A2", 2D) = "white" {}
_TexB1 ("Tex B1", 2D) = "white" {}
_TexB2 ("Tex B2", 2D) = "white" {}
_TexC1 ("Tex C1", 2D) = "white" {}
_TexC2 ("Tex C2", 2D) = "white" {}
_TexD1 ("Tex D1", 2D) = "white" {}
_TexD2 ("Tex D2", 2D) = "white" {}
_NormalMap ("Normal Map", 2D) = "bump" {}
_BumpAmount ("Bump Amount", Range(0, 1)) = 0.5
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Lighting Off
ZWrite Off

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
            #pragma multi_compile_fog

            #include "UnityCG.cginc"

sampler2D _TexA1;
sampler2D _TexA2;
sampler2D _TexB1;
sampler2D _TexB2;
sampler2D _TexC1;
sampler2D _TexC2;
sampler2D _TexD1;
sampler2D _TexD2;
sampler2D _NormalMap;
half _BumpAmount;

            struct v2f
            {
               float4 pos     : SV_POSITION;
   float2 uv      : TEXCOORD0;
   half3 normal: TEXCOORD1;
   #if WPM_BUMPMAP_ENABLED
   half3 tspace0 : TEXCOORD2; // tangent.x, bitangent.x, normal.x
               half3 tspace1 : TEXCOORD3; // tangent.y, bitangent.y, normal.y
               half3 tspace2 : TEXCOORD4; // tangent.z, bitangent.z, normal.z
               #endif
            };


            v2f vert (float4 vertex : POSITION, half3 normal : NORMAL, half4 tangent : TANGENT, float2 uv : TEXCOORD0) {
v2f o;
o.pos = UnityObjectToClipPos (vertex);
o.uv = uv;
half3 wNormal = UnityObjectToWorldNormal(normal);
o.normal = wNormal;

#if WPM_BUMPMAP_ENABLED
            half3 wTangent = UnityObjectToWorldDir(tangent.xyz);
            half tangentSign = tangent.w * unity_WorldTransformParams.w;
            half3 wBitangent = cross(wNormal, wTangent) * tangentSign;
                output the tangent space matrix
            o.tspace0 = half3(wTangent.x, wBitangent.x, wNormal.x);
            o.tspace1 = half3(wTangent.y, wBitangent.y, wNormal.y);
            o.tspace2 = half3(wTangent.z, wBitangent.z, wNormal.z);
            #endif

return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                // compute Earth pixel color
half4 color;

// compute Earth pixel color
if (i.uv.x<0.25)
{
if (i.uv.y>0.5)
{
color = tex2Dlod(_TexA1, float4(i.uv.x * 2.0, (i.uv.y - 0.5) * 2.0, 0, 0));
}
else
{
color = tex2Dlod(_TexA2, float4(i.uv.x * 2.0, i.uv.y * 2.0, 0, 0));
}
}
else if (i.uv.x < 0.5)
{
if (i.uv.y>0.5)
{
color = tex2Dlod(_TexB1, float4((i.uv.x - 0.25) * 2.0f, (i.uv.y - 0.5) * 2.0, 0, 0));
}
else
{
color = tex2Dlod(_TexB2, float4((i.uv.x - 0.25) * 2.0f, i.uv.y * 2.0, 0, 0));
}
}
else if (i.uv.x < 0.75)
{
if (i.uv.y>0.5)
{
color = tex2Dlod(_TexC1, float4((i.uv.x - 0.50) * 2.0f, (i.uv.y - 0.5) * 2.0, 0, 0));
}
else
{
color = tex2Dlod(_TexC2, float4((i.uv.x - 0.50) * 2.0f, i.uv.y * 2.0, 0, 0));
}
}
else if (i.uv.x < 1.0)
{
if (i.uv.y>0.5)
{
color = tex2Dlod(_TexD1, float4((i.uv.x - 0.75) * 2.0f, (i.uv.y - 0.5) * 2.0, 0, 0));
}
else
{
color = tex2Dlod(_TexD2, float4((i.uv.x - 0.75) * 2.0f, i.uv.y * 2.0, 0, 0));
}
}

// sphere normal (without bump-map)
half3 snormal = normalize(i.normal);

// transform normal from tangent to world space
#if WPM_BUMPMAP_ENABLED
half3 tnormal = UnpackNormal(tex2D(_NormalMap, i.uv));
                half3 worldNormal;
                worldNormal.x = dot(i.tspace0, tnormal);
                worldNormal.y = dot(i.tspace1, tnormal);
                worldNormal.z = dot(i.tspace2, tnormal);
                half3 normal = normalize(lerp(snormal, worldNormal, _BumpAmount));
                #else
                half3 normal = snormal;
                #endif

return color;
            }
            ENDCG
        }
    }
}

Mike O'Donnell

  • Guest
Re: Custom Shader
« Reply #7 on: July 22, 2019, 08:08:37 AM »
Never mind, I got it. I needed to up the multiplication from 2.0 to 4.0 to compensate for the added regions. Sorry for my carelessness, thanks for helping me out.

Kronnect

  • Administrator
  • Hero Member
  • *****
  • Posts: 5320
    • View Profile
Re: Custom Shader
« Reply #8 on: July 22, 2019, 11:50:25 AM »
Cool. Glad you got it.