0
\$\begingroup\$

Shader applied to plane

I'm not sure if using a shader is the best way for what I'm trying to achieve, but I would like to apply a color to each of the squares like in the picture and have the ability to change each color separately. I got the shader on this site: Link to Shader site

Shader "Custom/Geometry/Wireframe"
{
Properties
{
    [PowerSlider(3.0)]
_WireframeVal("Wireframe width", Range(0., 0.5)) = 0.05
    _FrontColor("Front color", color) = (1., 1., 1., 1.)
    _BackColor("Back color", color) = (1., 1., 1., 1.)
    [Toggle] _RemoveDiag("Remove diagonals?", Float) = 0.
}
    SubShader
{
    Tags{ "Queue" = "Geometry" "RenderType" = "Opaque" }

    Pass
{
    Cull Front
    CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom

    // Change "shader_feature" with "pragma_compile" if you want set this 
keyword from c# code
#pragma shader_feature __ _REMOVEDIAG_ON

#include "UnityCG.cginc"

    struct v2g {
    float4 worldPos : SV_POSITION;
};

struct g2f {
    float4 pos : SV_POSITION;
    float3 bary : TEXCOORD0;
};

v2g vert(appdata_base v) {
    v2g o;
    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
    return o;
}

[maxvertexcount(3)]
void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream) {
    float3 param = float3(0., 0., 0.);

#if _REMOVEDIAG_ON
    float EdgeA = length(IN[0].worldPos - IN[1].worldPos);
    float EdgeB = length(IN[1].worldPos - IN[2].worldPos);
    float EdgeC = length(IN[2].worldPos - IN[0].worldPos);

    if (EdgeA > EdgeB && EdgeA > EdgeC)
        param.y = 1.;
    else if (EdgeB > EdgeC && EdgeB > EdgeA)
        param.x = 1.;
    else
        param.z = 1.;
#endif

    g2f o;
    o.pos = mul(UNITY_MATRIX_VP, IN[0].worldPos);
    o.bary = float3(1., 0., 0.) + param;
    triStream.Append(o);
    o.pos = mul(UNITY_MATRIX_VP, IN[1].worldPos);
    o.bary = float3(0., 0., 1.) + param;
    triStream.Append(o);
    o.pos = mul(UNITY_MATRIX_VP, IN[2].worldPos);
    o.bary = float3(0., 1., 0.) + param;
    triStream.Append(o);
}

float _WireframeVal;
fixed4 _BackColor;

fixed4 frag(g2f i) : SV_Target{
    if (!any(bool3(i.bary.x < _WireframeVal, i.bary.y < _WireframeVal, 
[![Plane with Shader attached][1]][1]i.bary.z < _WireframeVal)))
    discard;

return _BackColor;
}

    ENDCG
}

    Pass
{
    Cull Back
    CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma geometry geom

    // Change "shader_feature" with "pragma_compile" if you want set this 
keyword from c# code
#pragma shader_feature __ _REMOVEDIAG_ON

#include "UnityCG.cginc"

    struct v2g {
    float4 worldPos : SV_POSITION;
};

struct g2f {
    float4 pos : SV_POSITION;
    float3 bary : TEXCOORD0;
};

v2g vert(appdata_base v) {
    v2g o;
    o.worldPos = mul(unity_ObjectToWorld, v.vertex);
    return o;
}

[maxvertexcount(3)]
void geom(triangle v2g IN[3], inout TriangleStream<g2f> triStream) {
    float3 param = float3(0., 0., 0.);

#if _REMOVEDIAG_ON
    float EdgeA = length(IN[0].worldPos - IN[1].worldPos);
    float EdgeB = length(IN[1].worldPos - IN[2].worldPos);
    float EdgeC = length(IN[2].worldPos - IN[0].worldPos);

    if (EdgeA > EdgeB && EdgeA > EdgeC)
        param.y = 1.;
    else if (EdgeB > EdgeC && EdgeB > EdgeA)
        param.x = 1.;
    else
        param.z = 1.;
#endif

    g2f o;
    o.pos = mul(UNITY_MATRIX_VP, IN[0].worldPos);
    o.bary = float3(1., 0., 0.) + param;
    triStream.Append(o);
    o.pos = mul(UNITY_MATRIX_VP, IN[1].worldPos);
    o.bary = float3(0., 0., 1.) + param;
    triStream.Append(o);
    o.pos = mul(UNITY_MATRIX_VP, IN[2].worldPos);
    o.bary = float3(0., 1., 0.) + param;
    triStream.Append(o);
}

float _WireframeVal;
fixed4 _FrontColor;

fixed4 frag(g2f i) : SV_Target{
    if (!any(bool3(i.bary.x <= _WireframeVal, i.bary.y <= _WireframeVal, 
i.bary.z <= _WireframeVal)))
    discard;

return _FrontColor;
}

    ENDCG
}
}
}
\$\endgroup\$
2
  • \$\begingroup\$ I would suggest you look into how to do "Instancing", you not only can assign a Matrix for position, orientation etc, you can also add other attributes such as colour and transparency. There are a number of tutorials and how to's out there on this, this should allow you to handle each square discreetly. \$\endgroup\$
    – ErnieDingo
    Aug 21 '18 at 1:21
  • \$\begingroup\$ I don't think a shader is going to solve this problem. Use a bunch of quads. \$\endgroup\$ May 2 '19 at 15:11
0
\$\begingroup\$

Share an idea for you. Use shader can do that but maybe use Plane meshes is more simple . Each grid is covered with a plane.You may change the plane color property of its material by what you desired. I kown you care about the performance.So please read this : MaterialPropertyBlock

MaterialPropertyBlock is used by Graphics.DrawMesh and Renderer.SetPropertyBlock. Use it in situations where you want to draw multiple objects with the same material, but slightly different properties. For example, if you want to slightly change the color of each mesh drawn.

At last, I supply a good example for this:

The magic of Material Property Blocks

This is my first answer at GameDevelopment.I hope this could help you.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.