Porting GLSL to HLSL (and later to Shader file)

OK…
I need some help getting the HLSL version to work…
I don’t need help porting into a Unity3D Shader file.
If I have a working HLSL shader, then it is no issue porting to Unity.
I am playing around with this process, with some success.
But before importing anything into an actual *.shader file
I have to do two things (since most examples are GLSL shaders)

  1. Get the GLSL shader to work. sometimes some minor tweaking or fixing is needed.
  2. Convert the GLSL shader to an HLSL shader.
    Once I get both working, the rest is mostly smooth sailing.

Now for some GLSL shaders, I will have no difficulty at all.
The ones that don’t work, the difficulty is in determining why?
I get no compiler errors, the GLSL displays + works…

I am mostly interested in WHY my example HLSL is not working, since this will absolutely help when I have the “same” issues porting other GLSL shaders.

I attached the 2 shader versions in a zip file.

  1. one is a GLSL version
  2. the other is a HLSL version .(converted from GLSL)

7894309–1005286–Squiggle_GLSL_HLSL.zip (4.18 KB)

1 Like

Here are the tools I am using in this process.
VS.Code - very good IDE/
Now the two important plugins for VS.Code are…

  1. An easy to use GLSL viewer (with built in uniform variable)
    Shader Toy - Visual Studio Marketplace

  2. An easy to use HLSL viewer (with built in uniform variable)
    HLSL preview - Visual Studio Marketplace

So here is what I do.

  1. Open/Create a new GLSL file in VS.Code.
  2. Add or Paste the GLSL code into it.
  3. Use the GLSL view to run/preview the shader.
  4. Fix/Tweak anything needed.

So once I get that working…onto the conversion process.

  1. Open/Create a new HLSL file in VS.Code.
  2. Add or Paste the HLSL code into it. (of course it goes without saying this will not work in GLSL viewer)
  3. Use the HLSL view to run/preview the shader.
  4. Fix/Tweak anything needed.

Now the conversion is mostly straight forward process.
I have to convert…
vec to float
And mix → lerp
mat to floatx
fract → frac
mod → fmod
most of the time, that is all the conversion that needs to be done.
I can usually get the HLSL working (with tweaks or minor fixes),
The rest is smooth sailing

Now for the example GLSL + HLSL program (attached in previous post)
I did this, but could not get the HLSL to work (the GLSL worked out of the box)
But could not figure out why it didn’t work…
Could somebody take a peak and see if something obvious is wrong?

Here is a preview of the working GLSL version.

1 Like

UPDATED HLSL FILE (attached)
There were some errors that didn’t get flagged in editor before.

7894354–1005301–Squiggle HLSL UPDATE.zip (2.13 KB)

What is correct GLSL to HLSL conversion for this code snippet?

ORIGINAL GLSL SNIPPET
float dif = dot(n, normalize(vec3(1,2,3)))*.5+.5;
vec3 col = vec3(dif);

CONVERTED HLSL SNIPPET(?)
float dif = dot(n, normalize(float3(1,2,3)))*.5+.5;
float3 col = float3(dif, dif, dif); <— Is this correct way to do it?
OR
float3 col = float3(dif, 0, 0); <— Is this correct way to do it?

float3 col = float3(dif, dif, dif);

1 Like

I think that might have fixed it.

How do you slow down a shader, it was running so fast it was hard to tell if it was working or not.
(the previous fix worked, but it was animating so fast it was hard to tell)

@MartinOrtiz you can also use this way:

float3 col = {dif, dif, dif};
1 Like

We can also use following syntax:

float3 col = dif.xxx;

or

float3 col = (float3) dif;

Additional note: instead of replace “vec” with “float” , in HLSL we can define own data types, so you can write following instruction: typedef vector <float, 2> vec2; typedef vector <float, 3> vec3;

Example:

Shader "Minimal Example"
{
    Subshader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex VSMain
            #pragma fragment PSMain
            #pragma target 5.0

            typedef vector <float, 3> vec3;

            float4 VSMain (float4 vertex : POSITION) : SV_POSITION
            {
                return UnityObjectToClipPos(vertex);
            }

            float4 PSMain (float4 vertex : SV_POSITION) : SV_Target
            {
                float dif = 1.0;
                vec3 col = (vec3) dif;
                return float4(col, 1.);
            }
            ENDCG
        }
    }
}
2 Likes

Additional note: instead of replace “vec” with “float” , in HLSL we can define own data types, so you can write following instruction: typedef vector <float, 2> vec2; typedef vector <float, 3> vec3;

I like this idea, because you can go back and forth when having trouble doing conversion.
So if I have trouble, rename the file as GLSL, and try that in the GLSL preview, to see if changes broke the GLSL version, without having to re=replace floats back to vecs.

Here’s a question, for most shaders, it makes sense to use a plane, and display the shader on a plane for a nice effect.

But I was wondering if it would be complicated to make the effect exist in 3D space itself?

For example, I have a shader (made up example)…
I did the whole conversion process and got it to work…
The shader has a cube that morphs back and forth from a cube to a sphere…
Now I can do all this, and use it as a material on a 2D plane…and it works of course.

But how hard would it be to make this a real 3D entity in the scene view?
So a player could walk around it etc…and view it…

So instead of a cube morphing back and forth, on a 2D plane…
It is morphing in the 3D space of the scene itself.
Would this be complicated to achieve?

The simplest way:

Set Main Camera to following position (0,50,0).
In Unity3D editor, add 3D Object/Quad as child object to Main Camera, then bind material with shader to the quad. Set quad position at (x=0 ; y=0; z=0.4 ).
Add CameraController to Main Camera. Play.

Shader "City"
{
    Subshader
    {
        Pass
        {
            CGPROGRAM
            #pragma vertex VSMain
            #pragma fragment PSMain
            #pragma target 5.0
                      
            struct Data
            {
                float4 screenPos : SV_POSITION;
                float3 worldPos : TEXCOORD1;
            };  

            float hash (float2 n)
            {
                return frac(sin(dot(n, float2(12.9898, 4.1414)))*43758.5453);
            }

            float map (float3 p)
            {
                float2 u = floor(p.xz*0.005*64.0)/64.0;
                float h = hash(u);
                h = p.y - lerp(0.0,8.0,pow(h,2.0));
                return max( min( h, 0.1), p.y-8.0 );
            }
          
            float4 color (float3 ro)
            {
                float m = ro.y/8.0;
                float4 buildings = float4 (m,m,m,1.0);
                float4 grass = float4(0,0.05,0,1);
                return lerp(buildings,grass,step(ro.y,0.1));
            }
          
            float4 raymarch (float3 ro, float3 rd)
            {
                for (int i=0; i<256; i++)
                {
                    float t = map(ro);
                    if (ro.x>300.0 || ro.x<-300.0 || ro.z>300.0 || ro.z<-300.0) break;
                    if ( t<0.001 ) return color(ro);
                    ro+=t*rd;
                }
                return float4(0.0,0.0,1.0,0.0);
            }

            Data VSMain (float4 vertex : POSITION)
            {
                Data vs;
                vs.screenPos = UnityObjectToClipPos(vertex);
                vs.worldPos = mul (unity_ObjectToWorld, vertex);
                return vs;
            }

            float4 PSMain (Data ps) : SV_TARGET
            {
                float3 worldPosition = ps.worldPos;
                float3 viewDirection = normalize(ps.worldPos-_WorldSpaceCameraPos.xyz);
                return raymarch (worldPosition,viewDirection);
            }

            ENDCG

        }
    }
}
using UnityEngine;

public class CameraController : MonoBehaviour
{
    public float mainSpeed = 10.0f;
    public float shiftAdd = 25.0f;
    public float maxShift = 100.0f;
    public float camSens = 0.25f;  
    float totalRun;  
    Vector3 lastMouse;

    void Start ()
    {
        totalRun = 1.0f;
        lastMouse = new Vector3(255.0f, 255.0f, 255.0f);       
    }

    Vector3 GetBaseInput()
    {
        Vector3 p_Velocity = new Vector3 (0.0f,0.0f,0.0f);
        if (Input.GetKey (KeyCode.W))
        {
            p_Velocity += new Vector3(0.0f, 0.0f , 1.0f);
        }
        if (Input.GetKey (KeyCode.S))
        {
            p_Velocity += new Vector3(0.0f, 0.0f , -1.0f);
        }
        if (Input.GetKey (KeyCode.A))
        {
            p_Velocity += new Vector3(-1.0f, 0.0f , 0.0f);
        }
        if (Input.GetKey (KeyCode.D))
        {
            p_Velocity += new Vector3(1.0f, 0.0f , 0.0f);
        }
        return p_Velocity;
    }
  
    void Update ()
    {
        lastMouse = Input.mousePosition - lastMouse ;
        lastMouse = new Vector3(-lastMouse.y * camSens, lastMouse.x * camSens, 0.0f );
        lastMouse = new Vector3(transform.eulerAngles.x + lastMouse.x , transform.eulerAngles.y + lastMouse.y, 0.0f);
        transform.eulerAngles = lastMouse;
        lastMouse =  Input.mousePosition;
        float f = 0.0f;
        var p = GetBaseInput();
        if (Input.GetKey (KeyCode.LeftShift))
        {
            totalRun += Time.deltaTime;
            p  = p * totalRun * shiftAdd;
            p.x = Mathf.Clamp(p.x, -maxShift, maxShift);
            p.y = Mathf.Clamp(p.y, -maxShift, maxShift);
            p.z = Mathf.Clamp(p.z, -maxShift, maxShift);
        }
        else
        {
            totalRun = Mathf.Clamp(totalRun * 0.5f, 1.0f, 1000.0f);
            p = p * mainSpeed;
        }
        p = p * Time.deltaTime;
        if (Input.GetKey(KeyCode.Space))
        {
            f = transform.position.y;
            transform.Translate(p);
            transform.position = new Vector3(transform.position.x,f,transform.position.z);
        }
        else
        {
            transform.Translate( p);
        }
    }
}
1 Like

Sounds like a great method!

Has anyone used glscc for converting glsl to hlsl? I haven’t quite gotten it to work right, so not sure if it’s been updated recently. Seems to be a couple up-to-date tools for hlsl-to-glsl conversion, but having trouble locating one that works for other direction.

1 Like