Standard Shader with Phong Tessellation?

Is there any way to add phong tessellation to the standard shader? I tried to add the Phong Tess CGPROGRAM into one of the subshaders but it creates a new tessellated surface over the standard shader surface instead of tesselating the existing one. I’m very new to shader programming and I have no idea what to try now. So, is there any way to add Phong Tessellation without having to go deep into the cgincludes? Thanks.

  • tessellate:TessFunction - use DX11 GPU tessellation; the function computes tessellation factors. See Surface Shader Tessellation for details.

I took a look over these pages and i tried to implement that into the standard shader. I added a CGPROGRAM block inside the sub shader (not in a pass, as the manual say) and inside i got the code for surface tessellation. The problem is that it creates a new tessellated surface over the regular one. What i need to do is to add tessellation into the Standard Shader surface program (which is in one of the cgincludes i think), and I have no idea where to look/what to edit.

You have to write it as a hull/domain shader. The surface shading works to generate a shader based on the code you provide, and generates quite a few different pieces into it. The standard shader is a fairly complex shader that is similar to say, a fully generated surface shader. There’s no way to add a keyword in.

If they don’t add one to the game soon, I may write some up (no promises… I’ll need them at some point but it might not be soon).

If you’re interested in reading;

Algorithms are in here, research paper here => http://perso.telecom-paristech.fr/~boubek/papers/PhongTessellation/PhongTessellation.pdf

I put up some basic tessellation here => Possible to pass surface shader tessellation output to vert/frag? - Unity Engine - Unity Discussions

But it’s only heightmap tessellation. Aras put up a demo package that I have, you can PM me if you want it, it’s basically what I posted except more complex, including heightmap, PN triangles, and both heightmap + PN triangles.

Thanks for the info. Well, it seems too hard for me (zero experience with shader programming) so I guess I will stop trying and focus on the other code in my project. Also thanks for the links, interesting information there :).
One more question, do you think it will be easier to create a new shader similar to the standard one but with tessellation using ShaderForge? It seems easier to work in a node based environment for me, but i never tried ShaderForge and I don’t know what it’s capable of.

Possibly! It depends on what you’re looking for. If you want all the additional features, like the detail textures, and things like that, then it’s a little rough. I learned a lot of my initial knowledge playing around with shader forge, and then going back and editing shaders by hand. I’d be the first to tell you that it’s not exactly a simple concept, you really have to wrap your mind around different concepts to understand what happens in a shader, so while SF makes it easier (and I recommend it!), it doesn’t necessarily make the whole idea of “thinking” in a way to make a shader easier. It’s taken me a good 6 months before I was actually somewhat comfortable with the mathematics, and I would call myself a quick learner.

I would say it depends on how driven you are to learn new things, or whether you’re just doing things in your spare time vs working for someone… how big a deal the price tag is… etc. It’s got some good resources, and can give easy, quick feedback on what you’re making, and it’s fun to play with the effects to create new things. It can also teach you quite a bit if you look at the shaders it generates. On the other hand, it’s not cheap, and if you use google you can find shaders all over to mess with, and those won’t translate into SF easily.

If you’re just looking for the physically based shading pipeline, I found this on the asset store => Unity Asset Store - The Best Assets for Game Making

But it is basically surface shaders that use the new lighting pipeline, and not actually the standard shader, with all the detail map inputs, customization, etc.

Well, I’m working in a small indie team (currently 6 persons, I’m the only programmer), on a project that will probably go on kickstarter and steam greenlight in some months from now, so time does matter. I guess it’s not worth to spend weeks/months just to learn about shaders (even if I want to and I’m really interested in shaders now :smile:), when there is a lot of gameplay code that needs to be written.

Also thanks for the asset link. I’m taking a look right now.

I get that. I’m working in a 3-person team (including me) but we’re all programmers, and the game is fully procedural, so the art assets we need can mostly be obtained from the asset stores, the core is all done via code (like voxels and etc), so I have become the defacto graphics programmer of the group, while they work with more structural code. Not into gameplay yet, though, so. Shaders are a fun thing to do, especially when you delve into compute shaders - you can process quite a bit with them.

Ah, sorry. I thought you had a self-writting surface shader using the standard surface function and wanted to add tessellation to that.

Editing the standard shaders isn’t something i’d recommend to anyone.

Plutoman covered it nicely, the assetstore link seems useful.

Yes, I wrote a new surface shader. It was pretty easy. There are still some tweaks to do but it looks almost the same as the standard shader.
Textures applied : Diffuse,Normal,Heightmap,SpecularMap with GlossMap in alphachannel, Occlusion map


Here is the code, if someone need it (Some parts of it might be incorrect, but it works) :

 Shader "MadGoat/Standard with Phong (Specular)" {
        Properties {
            //Tessellation
            _EdgeLength ("Edge length", Range(2,50)) = 5
            _Phong ("Phong Strengh", Range(-1,1)) = 0
            //Texture properties
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _Color("Color", color) = (1,1,1,0)
            _NormalMap ("Normalmap", 2D) = "bump" {}
            _NormalPow("Normal Power", Range(0,1)) = 0
            _ParallaxMap("HeightMap", 2D) = "white" {}
            _Parallax("Height", Range(0, 1)) = 0.5
            _SpecMap("Specular", 2D) = "white" {}
            _OccMap("Occlusion Map",2D) = "white"{}
            _OcclusionStrength("Occlusion Strenght", Range(0, 1)) = 0.5
            _EmissionMap("Emission Map",2D) = "black"{}
            _EmissionColor("EmissionColor", color) = (1,1,1,0)
          
            //_SpecPow ("Metallic", Range(0, 1)) = 0.5
            //_GlossPow ("Smoothness", Range(0, 1)) = 0.5
      
        }
        SubShader {
            Tags { "RenderType"="Opaque" }
            LOD 300
          
            CGPROGRAM
            #pragma surface surf StandardSpecular addshadow fullforwardshadows vertex:disp tessellate:tessEdge tessphong:_Phong
            #include "Tessellation.cginc"

            struct appdata {
                float4 vertex : POSITION;
                float4 tangent : TANGENT;
                float3 normal : NORMAL;
                float2 texcoord : TEXCOORD0;
                float2 texcoord1 : TEXCOORD1;
                float2 texcoord2 : TEXCOORD2;
            };

            float _Phong;
            float _EdgeLength;
          
            float4 tessEdge (appdata v0, appdata v1, appdata v2)
            {
                return UnityEdgeLengthBasedTess (v0.vertex, v1.vertex, v2.vertex, _EdgeLength);
            }

            void disp (inout appdata v)
            {
                //Do nothing
            }

            struct Input {
                float2 uv_MainTex;
                float2 uv_NormalMap;
                float3 viewDir;
            };

          
            sampler2D _MainTex;
            sampler2D _NormalMap;
            sampler2D _SpecMap;
            sampler2D _OccMap;
            sampler2D _EmissionMap;
            sampler2D _ParallaxMap;
          
            fixed4 _Color;
            fixed4 _EmissionColor;

            float _NormalPow;
            float _Parallax;
            float _OcclusionStrength;

            void surf (Input IN, inout SurfaceOutputStandardSpecular o) {
              
                half h = tex2D(_ParallaxMap, IN.uv_MainTex).g;
                float2 offset = ParallaxOffset1Step(h, _Parallax, IN.viewDir);
                IN.uv_MainTex += offset;
                IN.uv_NormalMap += offset;

                half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
                half4 s = tex2D (_SpecMap, IN.uv_MainTex);
                half4 O = tex2D (_OccMap, IN.uv_MainTex);
              
                o.Albedo = c.rgb;
                o.Specular = s.rgb;
                o.Smoothness = s.a;
                o.Occlusion = LerpOneTo(O.g, _OcclusionStrength);
                o.Emission = tex2D(_EmissionMap, IN.uv_MainTex).rgb * _EmissionColor.rgb;
                o.Normal = UnpackScaleNormal(tex2D (_NormalMap, IN.uv_NormalMap), _NormalPow);

            }
            ENDCG
        }
        FallBack "Diffuse"
    }