- Home /
Texture not mapped to UV CG shader
Hi there I am having a little trouble getting textures to map properly to UVs has anyone experienced this issue before and/or am I missing something? I just want it to map once across the uv space but it seems to be looping and when I move the camera it appears to slide across the surface.
Any help would be appreciated.
Kind Regards
Brian
Shader "Felinesoft/RelfectiveCG" {
Properties {
_Colour ("Colour", Color) = (0.5, 0.5, 0.5, 1)
_MainTex ("Base (RGB)", 2D) = "white" {}
_Cube("Reflection Map", Cube) = "" {}
_ReflectColour ("Reflection Colour", Color) = (1,1,1,0.5)
_ReflectBrightness ("Reflection Brightness", Float) = 1.0
_SpecularMap ("Specular / Reflection Map", 2D) = "white" {}
_r ("r?!?!", Range (0.0,10.0)) = 0.5
_d ("d?!?!", Range (0.0,10.0)) = 0.5
_light ("light", Vector) = (1,1,1)
_useNormNotTang ("use normal, not tangent", Range (0,1)) = 0
}
SubShader {
Pass {
CGPROGRAM
#pragma target 3.0
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
float3 blend3 ( float3 x )
{
float3 y = 1-x*x;
y = max(y,float3(0,0,0));
return ( y );
}
// SHADERLAB PROPERTIES
sampler2D _MainTex;
sampler2D _SpecularMap;
samplerCUBE _Cube;
fixed4 _ReflectColour;
fixed _ReflectBrightness;
fixed4 _Colour;
float4 _RimColour;
float _r;
float _d;
float3 _light;
float _useNormNotTang;
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float3 tangent : TEXCOORD0;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float3 normalDir : TEXCOORD0;
float3 viewDir : TEXCOORD1;
float2 uv;
};
vertexOutput vert(vertexInput input)
{
vertexOutput output;
float4x4 modelMatrix = _Object2World;
float4x4 modelMatrixInverse = _World2Object;
// multiplication with unity_Scale.w is unnecessary
// because we normalize transformed vectors
output.viewDir = float3(mul(modelMatrix, input.vertex)
- float4(_WorldSpaceCameraPos, 1.0));
output.normalDir = normalize(float3(mul(float4(input.normal, 0.0), modelMatrixInverse)));
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
output.uv = input.tangent.xy;
return output;
}
float4 frag(vertexOutput input) : COLOR
{
float4 position = float4(1,1,1,1);
//float4 position = input.pos; // THIS DOESNT WORK FOR SOME REASON NEEDS FIXING
float3 normal = input.normalDir;
float3 tangent = input.viewDir;
if (_useNormNotTang > 0)
{
tangent = normal;
}
float4x4 ModelViewProjectionMatrix = UNITY_MATRIX_MVP;
float4x4 ModelViewMatrix = UNITY_MATRIX_MV;
float4x4 ModelViewMatrixIT = UNITY_MATRIX_IT_MV;
float r = _r;
float d = _d;
float4 hiliteColor = float4(0.5,0.0,0.0,1.0);
float3 lightPosition = _light;
float3 eyePosition = _WorldSpaceCameraPos;
//float3 P = input.pos.xyz;
float3 P = position.xyz;
float3 L = normalize(lightPosition - P);
float3 V = normalize(eyePosition - P);
float3 H = L + V;
float3 N = mul((float3x3)ModelViewMatrixIT, normal);
float3 T = mul((float3x3)ModelViewMatrixIT, tangent);
float u = dot(T, H) * d;
float w = dot(N, H);
float e = r * u / w;
float c = exp(-e * e);
float4 anis = hiliteColor * float4(c * position.x, c * position.y, c * position.z, 1);
if (u < 0) u = -u;
float4 cdiff = float4(0, 0, 0, 1);
for (int n = 1; n < 8; n++)
{
float y = 2 * u / n - 1;
cdiff.xyz += blend3(float3(4 * (y - 0.75), 4 * (y - 0.5), 4 * (y - 0.25)));
}
// positionO = mul(ModelViewProjectionMatrix, position);
float4 diffractionOutput = cdiff + anis;
float3 reflectedDir =
reflect(input.viewDir, normalize(input.normalDir));
float4 mainTex = tex2D(_MainTex, input.viewDir.xy);
if (mainTex.a <= 0) discard;
float4 refAndDiff = ((texCUBE(_Cube, reflectedDir) * (_Colour * tex2D(_MainTex, input.viewDir.xy))) + diffractionOutput) * 0.5;
return refAndDiff;
}
ENDCG
}
}
}
You need to show us the texture that you're trying to map and the shader you're using - it's hard to see from the screenshot what the issue you're describing is.
Updated with shader and textures, also apologies for the state of the code its a mess due to prototyping after botching two shaders together.
Answer by tanoshimi · Jun 22, 2014 at 01:20 PM
Wow, that's a... err... interesting shader ;)
a.) You're passing uv (TEXCOORD0) into the vertex shader but rather confusingly are calling it "tangent":
struct vertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
float3 tangent : TEXCOORD0;
};
b.) You're then passing a "uv" member from the vertex to the fragment shader:
output.uv = input.tangent.xy;
c.) But, when you get to the fragment shader you're completely ignoring the uv member, and instead sampling the main texture based on the view direction, which explains why it "slides" across the surface when you move the camera:
float4 mainTex = tex2D(_MainTex, input.viewDir.xy);
...
So, firstly try changing that last line to:
float4 mainTex = tex2D(_MainTex, input.uv);
(you shouldn't need the xy swizzle since uv is only a float2 anyway)
But I'd strongly suggest you go back and name your variables a bit more carefully and ensure they all have the correct types, or else you're likely to run into further problems in the future.
haha It wasnt my na$$anonymous$$g convention, I am am combining a diffraction shader my colleague wrote with a reflection one that I modified ... its a mess and will be sorted once its working :)
The uv does partially work, thats why its there (I removed most of the commented out code some of which included the line you recommended) ... i.e. it sorts out the texture not mapping to the uvs but its still tiling and being warped by cameras position which is the main issue.
As I said, you can help yourself by cleaning up your code and actually working out why you've written what you have (you said that you and a colleague wrote it between you, so one of you should know what each line of code does!) - what are _r
and _d
for, for example? Why do you have an unused _Specular$$anonymous$$ap
? You do a number of calculations with position.x, .y, .z etc. which are all hard-coded to be just 1. And why do you have a variable called tangent that is actually the uv!
I've just tested it and replacing the tex2d sampler lookup with uv coordinates passed straight through from the vertex shader as described in my post above works for me to get a single _$$anonymous$$ainTex mapped across each face, which I think is what you're trying to achieve:
The shader isnt finished, the unused priorities are going to be used. The hardcoded values are going to be swapped out to the relevant values, the tangent variable is named that way because the shader was created from a diffraction function and thats what my colleague named it I assume to match the function... who knows?
As I said, I understand whats happening in the code as I am not looking at the variable names for more than reference so its arbitrary for the time being what they are called. I apologise for the inconvenience but I need it called this because I am co-referencing other shaders and it will be much more trouble than its worth to have a correct but different na$$anonymous$$g convention to the scripts I am working from.
replcing the tex2d sampler lookup with input.uv.xy doesnt work for me, it still has the same problem in which the textre looks like its sliding around relative to the camera position and distorting when you rotate the object.
Can you please verify that its line 127 that you changed to
float4 mainTex = tex2D(_$$anonymous$$ainTex, input.uv.xy);