- Home /
Shader Help: "Cannot implicitly convert 'float3' to 'float4'"
Hi,
I'm trying to experiment with using a shader to alter rendering based on the player position and a texture. I've taken a sample shader from the Unity docs and added a position vector input, as below:
Shader "Custom/Test" {
Properties {
_MainTex ("Texture", 2D) = "white" {}
_Detail ("Detail", 2D) = "gray" {}
_PlayerPos ("PlayerPos", Vector ) = (0,0,0,1)
}
SubShader {
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma debug
#pragma surface surf Lambert
struct Input {
float2 uv_MainTex;
float4 screenPos;
float4 worldPos;
};
sampler2D _MainTex;
sampler2D _Detail;
float4 _PlayerPos;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
float2 shadowUV = float2( IN.worldPos.x - _PlayerPos.x, IN.worldPos.z - _PlayerPos.z );
shadowUV /= 32.0;
shadowUV += float2(0.5,0.5);
o.Albedo *= tex2D (_Detail, shadowUV).r;
}
ENDCG
}
Fallback "Diffuse"
}
The problem is that this fails to compile with the "Cannot implicitly convert 'float3' to 'float4'" error in the title being flagged against the last "o.Albedo *=" line although obviously there's generated code involved that I can't see.
As there are no float3 variables involved, and I'm expressly building a float2, I'm a bit lost as to what the issue is. Can anyone shed some light?
Additional: The issue seems to be to do with the shadowUV value as simply setting it to "shadowUV = float2(0.5,0.5);" allows the shader to compile and run (although not do anything of interest of course). I've tried passing the player position as two floats instead of via a Vector4 and it does the same thing.
Some more experimenting:
float2 shadowUV = _PlayerPos.xz; //compiles
float2 shadowUV = worldPos.xz; //throws the conversion compile error
You don't have an o.Albedo += line. Do you mean the *= line?
Answer by ootsby · Feb 03, 2015 at 04:16 AM
I've worked it out, so I may as well add the answer to where I messed up.
I defined worldPos as a float4 in the Input struct when it's a float3. The fact that the error is thrown at the end of the chain of use rather than declaration made it a bit difficult to work out where the issue was.
Glad you sorted. Yeah, I hate shader program$$anonymous$$g for that very reason. Well, that and "backwards compatibility" isn't really a thing :P
Answer by carrollh · Feb 03, 2015 at 01:58 AM
Nutshell: You're in the CGProgram part, which is HLSL code. tex2D returns a float4 color value based on the things you pass in. Normally that's a sampler2D object and a tecture coordinate (or a float2). So you're good there. I'm not used to seeing tex2(..., ...). r anywhere. Normally it's .rgb or .a, but I'm not an HLSL wizard by any means. SurfaceOutput.Albedo is a half3 (float3?). So try changing .r to .rgb maybe.
Thanks but unfortunately .r or .rgb makes no difference to the compile issue. Presumably r does a scalar multiply while rgb would do a vector multiply.
The issue seems to be to do with the shadowUV value as simply setting it to "shadowUV = float2(0.5,0.5);" allows the shader to compile and run (although not do anything of interest of course). I've tried passing the player position as two floats ins$$anonymous$$d of via a Vector4 and it does the same thing.
I'll add this extra info to the question.
Your answer
Follow this Question
Related Questions
Order for Surface Shader / CG frag passes? 1 Answer
Shader with zwrite, shadows and alpha (special alpha) 2 Answers
Mobile Additive surface shader 0 Answers
How to force the compilation of a shader in Unity? 5 Answers
Multiple tex2D commands in fragment shader needed, is there a workaround? 0 Answers