Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by lokstok · Sep 30, 2011 at 09:05 PM · shadercgvertex shader

Blinn-Phong shader (vertex lit) from scratch.

Hey all, I have recently started messing around with shaders (GLSL, CG). I know that Unity has the awesome ShaderLab, which is aimed to get us started on shader development and hit the ground running. What I wanted to do was write a shader from scratch in Cg, without any of the help that ShaderLab provides, to help me get a better understanding of the stuff that goes into writing more complex vertex and fragment shaders.

So I am starting by implementing the most basic vertex lit Blinn-Phong shader. Here's the shader code..

 Shader "CgShaders/PerVertexBasicLightingShader" {
     Properties {
         _Ka ("Ka", Color) = (1, 1, 1, 1)
         _Kd ("Kd", Color) = (1, 1, 1, 1)
         _Ks ("Ks", Color) = (1, 1, 1, 1)
         _Shininess("Shininess", Range(0, 1)) = 0.5
         _LightColor ("Light Color", Color) = (1, 1, 1, 1)
         _LightPosition ("Light Position", Vector) = (0, 0, 0, 0)
         _EyePosition ("Eye Position", Vector) = (0, 0, 0, 0)
         _MainTex ("Base (RGB)", 2D) = "white" {}
     }
     SubShader {
         Tags { "RenderType"="Opaque" }
         Pass {
             CGPROGRAM
             #pragma vertex vert
             #pragma fragment frag
             #pragma target 3.0
             #include "UnityCG.cginc"
             
             //material properties
             half4 _Ka, _Kd, _Ks;
             float _Shininess;
             //light properties
             half4 _LightColor;
             float4 _LightPosition
             //eye properties
             float4 _EyePosition;
             
             sampler2D _MainTex;
             
             struct VertexShaderInput {
                 float4 vertex: POSITION;
                 float3 normal;
             };
             
             struct VertexShaderOutput {
                 float4 position: SV_POSITION;
                 half4 color: COLOR;
             };
             
             VertexShaderOutput vert(VertexShaderInput vi) {
                 VertexShaderOutput vso;
                 
                 //convert Object Space vertex and normal to View Space
                 float3 viewSpaceVertexPosition = mul(UNITY_MATRIX_MV, vi.vertex).xyz;
                 float3 viewSpaceNormal = mul(UNITY_MATRIX_IT_MV, float4(vi.normal, 0)).xyz;
                 
                 //the light and camera/eye are in World Space.. so convert them into Object Space
                 float4 objectSpaceLightPosition = mul(_World2Object, _LightPosition);
                 float4 objectSpaceEyePosition = mul(_World2Object, _EyePosition);
 
                 //then convert light and camera/eye position to View Space
                 float3 viewSpaceLightPosition = mul(UNITY_MATRIX_MV, objectSpaceLightPosition).xyz;
                 float3 viewSpaceEyePosition = mul(UNITY_MATRIX_MV, objectSpaceEyePosition).xyz;
                 
                 //ambient term
                 half4 ambient = _Ka;
                 
                 //diffuse term
                 float3 viewSpaceLightDirection = normalize(viewSpaceLightPosition - viewSpaceVertexPosition).xyz;
                 float diffuseLightIntensity = max(dot(viewSpaceNormal, viewSpaceLightDirection), 0);
                 half4 diffuse = _Kd * _LightColor * diffuseLightIntensity;
                 
                 //specular term
                 float3 viewSpaceViewDirection = normalize(viewSpaceEyePosition - viewSpaceVertexPosition).xyz;
                 float3 viewSpaceHalfVector = normalize(viewSpaceLightDirection + viewSpaceViewDirection).xyz;
                 float specularLightIntensity = pow(max(dot(viewSpaceNormal, viewSpaceHalfVector), 0), _Shininess);
                 if (diffuseLightIntensity <= 0)
                     specularLightIntensity = 0;
                 half4 specular = _Ks * _LightColor * specularLightIntensity;
                 
                 //this is what is going to be passed to the fragment shader
                 vso.color = saturate(ambient + diffuse + specular);
                 vso.position = mul(UNITY_MATRIX_MVP, vi.vertex);
                 
                 return vso;
             }
             
             half4 frag(VertexShaderOutput vo) : COLOR {
                 half4 color = vo.color;
                 return color;
             }
             
             ENDCG
         }
     } 
     FallBack "Diffuse"
 }

The Light in this case, is a small sphere which I am orbiting around my object (the shader is attached to the material of this object). So the _LightPosition is the lightObject.transform.position being sent in the Update() function of a script attached to the object. The _EyePosition is the transform.position of the lone camera in the scene being sent in a similar manner.

The thing I am assuming here (this is where I think I might be going wrong), is that the Light and Eye positions are in world space. That is why I need to do the conversion back to object space and then to view space. I am doing this since there is no view matrix available to take me from world space to view space directly.

So the resulting output that I am getting seems all wrong. The effect on the target object (cube) definitely isn't the correct one. ![alt text][1]

![alt text][2]

The first image is with the light (the small sphere) behind the cube. So the faces seen should not be lit at all. The 2nd image is with the light in front of the cube.

I know this question is rather large by now, but hopefully someone should be able to guide me as to what it is I should be doing to get this correct. I am positive that once this small hurdle is done, I should have a clearer understanding of how this works.

Thanks! [1]: http://www.akshayloke.com/CgShaders/BlinnPhong1.PNG [2]: http://www.akshayloke.com/CgShaders/BlinnPhong2.PNG

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by Bunny83 · Sep 30, 2011 at 09:44 PM

You should take a look into the cg-include file, located in your Unity install path ("\Editor\Data\CGIncludes\UnityCG.cginc"). It looks like you pass your own custom parameters to the shader, but Unity already passes tons of global static and object specific information to the shader. Even a lot of helper functions are defined there so you don't have to do all from scratch ;)

It gives you a great overview how Unity handles some stuff. Afaik the source of the built-in shaders are available for download somewhere in the forums. But be careful the syntax have changed a lot between the last Unity versions so some stuff is deprecated.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Swizzling cube face to other faces in the cube 1 Answer

How to force the compilation of a shader in Unity? 5 Answers

Where is model space origin in shaderlab? 1 Answer

Vertex Shader Properties Issu 1 Answer

UnityPixelSnap in custom vertex shader behaves differently to implementation in default sprite shader. 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges