I'm using three glcontrols say GlControl1, GlControl2, GlControl3.
And I have two textures stexture1 and stexture2. Where stexture1 is displaying in glcontrol2. And right half portion of stexture2 is displaying on glcontrol1 and left half is dispalying on glcontrol3.
Now I want to apply projection on these three glcontrols. Using this link I can apply it successfully on glcontrol2 since it is displaying the texture fully.
But when applying on glcontrol1 and glcontrol3 it is not working well.
Please see the shader code I'm trying with.
GL.ShaderSource(fragShader, #"precision highp float;
uniform sampler2D sTexture_1;
uniform sampler2D sTexture_2;
uniform float sSelectedRangeLeft;
uniform float sSelectedRangeRight;
uniform float sSelectedRangeLeftEnd;
uniform float sSelectedRangeRightEnd;
uniform int sCurrentGLControl;
varying vec2 vTexCoordIn;
void main ()
{
vec2 vTexCoord=vec2(vTexCoordIn.x,vTexCoordIn.y);
float rightsliderStartval=sSelectedRangeRight;//0.5(value between 0.5 and 1.0)
float rightsliderEndval=sSelectedRangeRightEnd;//1.0(value between 0.5 and 1.0)
float rightsliderDelta=rightsliderEndval-rightsliderStartval;
float leftsliderStartval=sSelectedRangeLeftEnd;//0.0(value between 0 and 0.5)
float leftsliderEndval=sSelectedRangeLeft;//0.5(value between 0 and 0.5)
float leftsliderDelta=leftsliderEndval-leftsliderStartval;
if(sCurrentGLControl==1)
{
if ( vTexCoord.x <=1.0 && vTexCoord.x > 1.0 -rightsliderDelta)
{
vec4 colorLeft=texture2D (sTexture_2, vec2(vTexCoord.x -(1.0-rightsliderEndval), vTexCoord.y));
//i want to show this result in a projected view like glcontrol2
gl_FragColor = colorLeft;
}
}
else if(sCurrentGLControl==3)
{
if ( vTexCoord.x <=leftsliderDelta )
{
vec4 colorRight=texture2D (sTexture_2, vec2((vTexCoord.x)+leftsliderStartval, vTexCoord.y+sSelectedRightEndVerticalShift));
//i want to show this result in a projected view like glcontrol2
gl_FragColor = colorRight;
}
}
else if(sCurrentGLControl==2)
{ //Projection works fine
vec2 pos = vTexCoord.xy * 2.0 - 1.0;
float b = 0.3;
float v_scale = (1.0 + b) / (1.0 + b * sqrt(1.0 - pos.x*pos.x));
float u = asin( pos.x ) / 3.1415 + 0.5;
float v = (pos.y * v_scale) * 0.5 + 0.5;
if ( v < 0.0 || v > 1.0 )
discard;
vec3 texColor = texture2D( sTexture_1, vec2(u, v) ).rgb;
gl_FragColor = vec4( texColor.rgb, 1.0 );
}
}");
==================================================================
if (glControl.Name == "glControl1")
{
GL.Viewport(new Rectangle(-glControl.Width, 0, glControl.Width*2.0, glControl.Height));
}
else if (glControl.Name == "glControl2")
{
GL.Viewport(new Rectangle(0, 0, glControl.Width , glControl.Height));
}
else
{
GL.Viewport(new Rectangle(0, 0, glControl.Width*2.0, glControl.Height));
}
If you don't want to distort the "discarded" area, the just keep the original texture coordinate:
precision highp float;
uniform sampler2D sTexture;
varying vec2 vTexCoordIn;
void main ()
{
vec2 uv = vTexCoordIn.xy
if (vTexCoordIn.x >= 0.7 && vTexCoordIn.x <= 0.9)
{
vec2 pos = vTexCoordIn.xy * 2.0 - 1.0;
float b = 0.3;
float v_scale = (1.0 + b) / (1.0 + b * sqrt(1.0 - pos.x*pos.x));
float u = asin( pos.x ) / 3.1415 + 0.5;
float v = (pos.y * v_scale) * 0.5 + 0.5;
if (v >= 0.0 && v <= 1.0)
uv = vec2(u, v);
}
vec3 texColor = texture2D(sTexture, uv).rgb;
gl_FragColor = vec4(texColor.rgb, 1.0);
}
Edit according to the changes of the question:
If you just want to show a part of the texture, then you've to map the texture coordinate from the range [0, 1] to the range [left, right], when the texture is looked up:
u = u * rightsliderDelta + rightsliderStartval;
vec3 texColor = texture2D( sTexture_2, vec2(u, v) ).rgb;
Apply this to your code as follows:
e.g.:
void main ()
{
vec2 vTexCoord=vec2(vTexCoordIn.x,vTexCoordIn.y);
float rightsliderStartval=sSelectedRangeRight;//0.5(value between 0.5 and 1.0)
float rightsliderEndval=sSelectedRangeRightEnd;//1.0(value between 0.5 and 1.0)
float rightsliderDelta=rightsliderEndval-rightsliderStartval;
// [...]
if(sCurrentGLControl==1) {
vec2 pos = vTexCoord.xy * 2.0 - 1.0;
float b = 0.3;
float v_scale = (1.0 + b) / (1.0 + b * sqrt(1.0 - pos.x*pos.x));
float u = asin( pos.x ) / 3.1415 + 0.5;
float v = (pos.y * v_scale) * 0.5 + 0.5;
if ( v < 0.0 || v > 1.0 )
discard;
u = u * rightsliderDelta + rightsliderStartval;
vec3 colorLeft = texture2D( sTexture_2, vec2(u, v) ).rgb;
gl_FragColor = vec4( colorLeft .rgb, 1.0 );
}
// [...]
}
Related
I want to show selected area from second half of an image (This is the range from 0.5 to 1.0) in my glcontrol. For that I have used two variables rightsliderStartval(any value between 0.5 and 1.0)
and rightsliderEndval(any value between 1.0 and 0.5). I want exactly the selected area between this rightsliderStartval and rightsliderEndval. When trying like below selected area is getting but it get stretched.
decimal RateOfResolution = (decimal)videoSource.VideoResolution.FrameSize.Width / (decimal)videoSource.VideoResolution.FrameSize.Height;
int openGLwidth = (this._Screenwidth / 3) - 40;
int openGLheight = Convert.ToInt32(screenWidthbyThree / RateOfResolution);
glControl.Width = openGLwidth;
glControl.Height = openGLheight;
GL.Viewport(new Rectangle(0, 0, glControl.Width, glControl.Height));
public void CreateShaders()
{
/***********Vert Shader********************/
vertShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertShader, #"attribute vec3 a_position;
varying vec2 vTexCoordIn;
void main() {
vTexCoordIn=( a_position.xy+1)/2 ;
gl_Position = vec4(a_position,1);
}");
GL.CompileShader(vertShader);
/***********Frag Shader ****************/
fragShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragShader, #"precision highp float;
uniform sampler2D sTexture;
varying vec2 vTexCoordIn;
void main ()
{
vec2 vTexCoord=vec2(vTexCoordIn.x,vTexCoordIn.y);
float rightsliderStartval=0.6;//0.5 to 1.0
float rightsliderEndval=0.8;//1.0 to 0.5
float rightsliderDelta=rightsliderEndval-rightsliderStartval;
if (vTexCoordIn.x < 0.5)
discard;
float u = mix(rightsliderStartval, rightsliderEndval, (vTexCoordIn.x-0.5) * 2.0);
vec4 color = texture2D(sTexture, vec2(u, vTexCoordIn.y));
gl_FragColor = color;
}");
GL.CompileShader(fragShader);
}
In Screenshot, White line represent center of image. I Want to show area between yellow and orange line.
If you want to skip a some parts of the texture, then you can use the discard keyword. This command causes the fragment's output values to be discarded and the fragments are not drawn at all.
If you've a rectangular area and you want to draw only in the 2nd half of the rectangular area, then you've to discard the fragments in the 1st half:
if (vTexCoordIn.x < 0.5)
discard;
If you want to draw the range from rightsliderStartval to rightsliderEndval in the 2nd half of the rectangular area, then you have to map the rang [0.5, 1.0] incoming texture coordinate vTexCoordIn.x to [rightsliderStartval, rightsliderEndval]:
float w = (vTexCoordIn.x-0.5) * 2.0; // [0.5, 1.0] -> [0.0, 1.0]
float u = mix(rightsliderStartval, rightsliderEndval, w); // [0.0, 1.0] -> [0.7, 0.9]
This leads to the fragment shader:
precision highp float;
uniform sampler2D sTexture;
varying vec2 vTexCoordIn;
void main ()
{
float rightsliderStartval = 0.7;
float rightsliderEndval = 0.9;
if (vTexCoordIn.x < 0.5)
discard;
float u = mix(rightsliderStartval, rightsliderEndval, (vTexCoordIn.x-0.5) * 2.0);
vec4 color = texture2D(sTexture, vec2(u, vTexCoordIn.y));
gl_FragColor = color;
}
If you don't want that the image is stretched then you've 2 possibilities.
Either discard the region from 0.0 to 0.7 and 0.9 to 1.0:
precision highp float;
uniform sampler2D sTexture;
varying vec2 vTexCoordIn;
void main ()
{
float rightsliderStartval = 0.7;
float rightsliderEndval = 0.9;
if (vTexCoordIn.x < 0.7 || vTexCoordIn.x > 0.9)
discard;
vec4 color = texture2D(sTexture, vTexCoordIn.xy));
gl_FragColor = color;
}
Or scale the image in the y direction, too:
precision highp float;
uniform sampler2D sTexture;
varying vec2 vTexCoordIn;
void main ()
{
float rightsliderStartval = 0.7;
float rightsliderEndval = 0.9;
if (vTexCoordIn.x < 0.5)
discard;
float u = mix(rightsliderStartval, rightsliderEndval, (vTexCoordIn.x-0.5) * 2.0);
float v_scale = (rightsliderEndval - rightsliderStartval) / 0.5;
float v = vTexCoordIn.y * v_scale + (1.0 - v_scale) / 2.0;;
vec4 color = texture2D(sTexture, vec2(u, v));
gl_FragColor = color;
}
I'm trying to create a custom shader in unity. Following is the code for my shader.
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
// Default Vertex Shader
v2f vert(appdata_img v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = MultiplyUV(UNITY_MATRIX_TEXTURE0, v.texcoord.xy);
return o;
}
// Parameters
sampler2D _MainTex;
float _FOV;
// Alpha is the ratio of pixel density: width to height
float _Alpha;
uniform float4x4 _UnityDisplayTransform;
// Fragment Shader: Remap the texture coordinates to combine
// barrel distortion and disparity video display
fixed4 frag(v2f i) : COLOR {
float2 uv1, uv2, uv3;
float t1, t2;
float offset;
// uv1 is the remap of left and right screen to a full screen
uv1 = i.uv - 0.5;
uv1.x = uv1.x * 2 - 0.5 + step(i.uv.x, 0.5);
t1 = sqrt(1.0 - uv1.x * uv1.x - uv1.y * uv1.y);
t2 = 1.0 / (t1 * tan(_FOV * 0.5));
// uv2 is the remap of side screen with barrel distortion
uv2 = uv1 * t2 + 0.5;
// black color for out-of-range pixels
if (uv2.x >= 1.5 || uv2.y >= 1.0 || uv2.x <= -0.5 || uv2.y <= 0.0) {
return fixed4(0, 0, 0, 1);
} else {
offset = 0.5 - _Alpha * 0.5;
// uv3 is the remap of image texture
uv3 = uv2;
uv3.x = uv2.x * _Alpha + offset;
return tex2D(_MainTex, uv3);
}
}
ENDCG
}
Im getting the following output with the same. This is the effect that I get when I apply the shader.
However Im desiring to get a two perfect squares instead of the curved edges. How can I be able to sort it out?
This should work:
Shader "Custom/FakeAR"
{
Properties{
_MainTex("", 2D) = "white" {}
_FOV("FOV", Range(1, 2)) = 1.6
_Disparity("Disparity", Range(0, 0.3)) = 0.1
_Alpha("Alpha", Range(0, 2.0)) = 1.0
}
SubShader{
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f {
float4 pos : POSITION;
float2 uv : TEXCOORD0;
};
// Default Vertex Shader
v2f vert(appdata_img v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = MultiplyUV(UNITY_MATRIX_TEXTURE0, v.texcoord.xy);
return o;
}
// Parameters
sampler2D _MainTex;
float _FOV;
// Alpha is the ratio of pixel density: width to height
float _Alpha;
// Disparity is the portion to separate
// larger disparity cause closer stereovision
float _Disparity;
// Fragment Shader: Remap the texture coordinates to combine
// barrel distortion and disparity video display
fixed4 frag(v2f i) : COLOR
{
float2 uv1, uv2, uv3;
float t1, t2;
float offset;
// uv1 is the remap of left and right screen to a full screen
uv1 = i.uv - 0.5;
uv1.x = uv1.x * 2 - 0.5 + sign(i.uv.x < 0.5);
//t1 = sqrt(1.0 - uv1.x * uv1.x - uv1.y * uv1.y);
t2 = _FOV;// 1.0 / (t1 * tan(_FOV * 0.5));
// uv2 is the remap of side screen with barrel distortion
uv2 = uv1 * t2 + 0.5;
// black color for out-of-range pixels
if (uv2.x >= 1 || uv2.y >= 1 || uv2.x <= 0 || uv2.y <= 0) {
return fixed4(0, 0, 0, 1);
}
else {
offset = 0.5 - _Alpha * 0.5 + _Disparity * 0.5 - _Disparity * sign(i.uv.x < 0.5);
// uv3 is the remap of image texture
uv3 = uv2;
uv3.x = uv2.x * _Alpha + offset;
return tex2D(_MainTex, uv3);
}
//float4 color = tex2D(_MainTex, i.uv);
//return 1 - color;
}
ENDCG
}
}
FallBack "Diffuse"
}
I'm going to write a program to view dwg file. I'm using SharpGL library.
I'm wrote a mouse control camera for 3D.
This is a code:
private void Device_OpenGLDraw(object sender, SharpGL.SceneGraph.OpenGLEventArgs args)
{
OpenGL gl = args.OpenGL;
gl.ClearColor((float)s3.Value, (float)s2.Value, (float)s1.Value, 0f);
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
gl.LoadIdentity();
gl.MatrixMode(OpenGL.GL_PROJECTION);
gl.LoadIdentity();
gl.Ortho(-wheelx, wheelx, -wheely, wheely, 0.1f, 1000000000.0f);
gl.MatrixMode(OpenGL.GL_MODELVIEW);
gl.Rotate(xrot, 1.0, 0.0, 0.0);
gl.Rotate(yrot, 0.0, 1.0, 0.0);
gl.Translate(-xpos, -ypos, -zpos);
DrawScene();
gl.Flush();
}
private void Device_MouseMove(object sender, MouseEventArgs e)
{
System.Windows.Point position = Mouse.GetPosition(Device);
x = (int)Math.Ceiling(position.X);
y = -(int)Math.Ceiling(position.Y);
if (e.MiddleButton == MouseButtonState.Pressed)
{
Cursor = Cursors.Hand;
diffx = x - lastx; //check the difference between the
diffy = y - lasty; //check the difference between the
xrot += (float)diffy * 0.05f * (float)Math.Min(wheelx, wheely); ; //set the xrot to xrot with the addition
yrot += (float)diffx * 0.05f * (float)Math.Min(wheelx, wheely); ; //set the xrot to yrot with the addition
if (xrot < 0)
{
xrot = 360;
}
if (xrot > 360)
{
xrot = 0;
}
if (yrot < 0)
{
yrot = 360;
}
if (yrot > 360)
{
yrot = 0;
}
}
if (e.LeftButton == MouseButtonState.Pressed)
{
diffx = x - lastx; //check the difference between the
diffy = y - lasty; //check the difference between the
float xrotrad, yrotrad;
yrotrad = (yrot / 180 * PI);
xrotrad = (xrot / 180 * PI);
float xs = (float)(Math.Tan(xrotrad));
float xc = (float)(Math.Cos(xrotrad));
float yc = (float)(Math.Cos(yrotrad));
float ys = (float)(Math.Sin(yrotrad));
ypos -= (xc * (float)diffy)* 0.003f * (float)Math.Min(wheelx, wheely);
zpos -= (-yc * (float)diffy + ys * (float)diffx) * 0.003f * (float)Math.Min(wheelx, wheely);
xpos += (-ys * (float)diffy - yc * (float)diffx) * 0.003f * (float)Math.Min(wheelx, wheely);
l5.Content = xc;
}
lastx = x; //set lastx to the current x position
lasty = y; //set lasty to the current y position
}
For 2D camera works a good. On 3D a have problem:
When X angle is between 0-180 degree, vertical moving works a good, but X angle is between 180-360 (ABOUT 315 degree) , vertical moving not working properly.
What am I doing wrong?
I implemented this code from another question, and it works really well.
The issue I am having is repeatedly mixing two colors slowly results in black. Here is an example of the effect.
I am using C#, and I have the RGBA of two colors, (background & foreground) in a Color32 type - 1 byte for red, green, blue and alpha. At the moment I am converting the 0-255 to 0-1 but I think there is some floating point conversion issues.
What's a way that won't have this effect?
EDIT: Here is the code I am using. currentColor is the canvas (background) and brushColor is the foreground.
float bg_r = ((float)currentColor.r) / 255.0f;
float bg_g = ((float)currentColor.g) / 255.0f;
float bg_b = ((float)currentColor.b) / 255.0f;
float bg_a = ((float)currentColor.a) / 255.0f;
float bg_r_a = bg_r * bg_a;
float bg_g_a = bg_g * bg_a;
float bg_b_a = bg_b * bg_a;
float fg_r = ((float)brushColor.r) / 255.0f;
float fg_g = ((float)brushColor.g) / 255.0f;
float fg_b = ((float)brushColor.b) / 255.0f;
float fg_a = (((float)brushColor.a) / 255.0f) * brush.pressure; // 0 - 1
float fg_r_a = fg_r * fg_a;
float fg_g_a = fg_g * fg_a;
float fg_b_a = fg_b * fg_a;
float col_r_a = fg_r_a + bg_r_a * ( 1.0f - fg_a );
float col_g_a = fg_g_a + bg_g_a * ( 1.0f - fg_a );
float col_b_a = fg_b_a + bg_b_a * ( 1.0f - fg_a );
float col_a = fg_a + bg_a * ( 1.0f - fg_a );
float col_r = col_r_a / col_a;
float col_g = col_g_a / col_a;
float col_b = col_b_a / col_a;
byte colR = (byte)Mathf.Clamp( col_r * 255.0f, 0.0f, 255.0f );
byte colG = (byte)Mathf.Clamp( col_g * 255.0f, 0.0f, 255.0f );
byte colB = (byte)Mathf.Clamp( col_b * 255.0f, 0.0f, 255.0f );
byte colA = (byte)Mathf.Clamp( col_a * 255.0f, 0.0f, 255.0f );
Color32 outputColor = new Color32( colR, colG, colB, colA );
Link: http://pastebin.com/hXkKSYLe
The problem is likely in these lines:
byte colR = (byte)Mathf.Clamp( col_r * 255.0f, 0.0f, 255.0f );
Specifically, the (byte) cast. Casting from a floating-point type to an integral type will truncate the fractional part:
Console.WriteLine((byte)1.9f); // Outputs "1"
Console.WriteLine((int)-1.9f); // Outputs "-1"
So after each conversion back to bytes, you'll lose an average of 0.5 byte-sized increments, and after an average of 512 conversions, your color will drift to black.
Try adding a call to Math.Round to remove the drift.
byte colR = (byte)Math.Round(Mathf.Clamp( col_r * 255.0f, 0.0f, 255.0f ));
I'm looking for better way to calculate if one object facing another or one is behind another. So far I've been able to create this but it seems to not working 100% correctly :(
I also think it should be in radians rather then degrees.
public static float GetAngle(float x1, float y1, float x2, float y2)
{
float xDiff = x2 - x1;
float yDiff = y2 - y1;
var angle = RadianToDegree((float)Math.Atan2(yDiff, xDiff));
if (angle < 0)
return 360 + angle;
return angle;
}
public static bool IsFacing(Point obj, float rotationAngle, Point target, float arcDegree = 180)
{
var angleBetweenPoints = GetAngle(obj, target);
return rotationAngle >= angleBetweenPoints - arcDegree / 2 && rotationAngle <= angleBetweenPoints + arcDegree / 2;
}
public static bool IsBehind(Point obj, float rotationAngle, Point target, float arcDegree = 180)
{
var angleBetweenPoints = GetAngle(obj, target);
var backViewAngle = rotationAngle > 180 ? rotationAngle - 180 : 180 - rotationAngle;
return backViewAngle >= angleBetweenPoints - arcDegree / 2 && backViewAngle <= angleBetweenPoints + arcDegree / 2;
}
At first glance it looks like your problem is in the test of rotationAngle vs angleBetweenPoints in the IsFacing() method.
Given:
rotationAngle = 0, angleBetweenPoints = 350, arcDegree = 180
then the test will be:
test = 0 >= (350 - 180 / 2) && 0 <= (350 + 180 / 2)
= 0 >= 260 && 0 <= 440
= false
This will happen fairly often, and is due to the use of the range [0..360] for your angles. While this is useful in some cases, this is not one of those cases. Far more useful here is to get the difference in the heading and target angles in the range [-180..180], then the comparison to arcDegree becomes much simpler.
Try this:
// Adjust a value to fit in the specified range
public static float Clamp(float v, float low, float high)
{
float range = high - low;
float modifier = ((int)((v - low) / range) - (v < low ? 1 : 0)) * range;
v -= modifier;
return v;
}
// Get the angle between a point+heading and another point
// Returns an angle in the range (-180..180) where:
// res < 0 target clockwise from heading
// res == 0 target at heading
// res > 0 target counter-clockwise from heading
static float RelativeAngle(float heading, float x1, float y1, float x2, float y2)
{
// get angle between points in world coordinates
float angle = RadianToDegree((float)Math.Atan2(y2 - y1, x2 - x1));
// adjust to local coordinates and normalize
return Clamp(angle - heading, -180, 180);
}
public static bool IsFacing(Point obj, float rotationAngle, Point target, float arcDegree = 180)
{
var angleBetweenPoints = RelativeAngle(rotationAngle, obj.x, obj.y, target.x, target.y);
return angleBetweenPoints >= -(arcDegree / 2) && angleBetweenPoints <= (arcDegre / 2);
}