- Home /
Modify some texture pixels in fragment function
Greetings,
Now I have a camera moving over a mesh and what I'm trying to do is painting the area covered by this camera (between the 4 frustrum corners).
I've been able to create a runtime Texture2D in a projector, get that texture, get the UV coordinates corresponding to the four frustrum corners hit points and modifying all pixels of my texture with SetPixels32(). This works "fine", I move the camera and it leaves a rectangular spot on the mesh according to the area covered which I can show/hide just by activating the projector. The problem is that this code makes graphics performance to fall every time it executes texture.Apply().
What I'm looking for is the SetPixels32() sentence needed to modify these same texture pixels inside a fragment shader. The CG code needed to take this sampler2D _ProjectedTexture and modify its pixels in the fragment function of a shader.
Thanks in advance.
Answer by Cherno · Mar 16, 2017 at 10:35 PM
I've taken the basic Unlit shader from this page: Vertex and fragment shader examples
and added some functionality to it. Namely, you specify min and max uv values and a color and if a pixel is inside the uv values, it is rendered in the specified color. You could possibly optimize this by combing the uv properties into float2 or float4, but I'm not sure how that would work with the PropertyBlock code below.
Disclaimer: I didn't test this.
Shader "Unlit/NewUnlitShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_UVMin_x("UV Min_x", float) = 0
_UVMin_y("UV Min_y", float) = 0
_UVMax_x("UV Max_x", float) = 0
_UVMax_y("UV Max_y", float) = 0
_ProjectorColor("Projector Color", Color) = (1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _UVMin_x;
float _UVMin_y;
float _UVMax_x;
float _UVMax_y;
fixed4 _ProjectorColor;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
if(i.uv.x >= _UVMin_x && i.uv.y >= _UVMin_y && i.uv.y <= _UVMax_x && i.uv.y <= _UVMax_y)
{
col = _ProjectorColor;
}
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
To access these added variables, you need to include a function like this in a script:
Renderer myRenderer
void UpdateOutline(Color color, Vector2 uv_min, Vector2 uv_max, ) {
MaterialPropertyBlock mpb = new MaterialPropertyBlock();
if (myRenderer!= null) {
myRenderer.GetPropertyBlock(mpb);
mpb.SetFloat("_UVMin_x", uv_min.x);
mpb.SetFloat("_UVMin_y", uv_min.y);
mpb.SetFloat("_UVMax_x", uv_max.x);
mpb.SetFloat("_UVMax_y", uv_max.y);
mpb.SetColor("_ProjectorColor", color);
myRenderer.SetPropertyBlock(mpb);
}
}
Thanks for your answer Cherno,
Your code surely works but made me realize that I've probably made the wrong question. I know how to modify texture pixels every frame, but what I'm trying to do is leaving a scar in that texture. I mean modifying it persistently.
Your answer
![](https://koobas.hobune.stream/wayback/20220612113226im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Overlay Effect Shader - Very slow in mobile device 1 Answer
Do TEXCOORDS need to be in sequence? 1 Answer
RenderTexture and DrawTexture using material is not working 0 Answers
Graphics.DrawTexture vs GUI.DrawTexture vs Graphics.Blit 0 Answers
How to implement scaling without scaling the texture. 1 Answer