I am trying to move my texture to the center of the pixel as stated here OpenGL Texture Coordinates in Pixel Space but am struggling to do so. Are the pixels we are trying to center on in the texture or on the screen? How do we access them? Here is my vertex shader:
"uniform mat4 " + ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX + ";\n" +
"attribute vec4 " + ShaderProgramConstants.ATTRIBUTE_POSITION + ";\n" +
"attribute vec4 " + ShaderProgramConstants.ATTRIBUTE_COLOR + ";\n" +
"attribute vec2 " + ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES + ";\n" +
"varying vec4 " + ShaderProgramConstants.VARYING_COLOR + ";\n" +
"varying vec2 " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + ";\n" +
"void main() {\n" +
" " + ShaderProgramConstants.VARYING_COLOR + " = " + ShaderProgramConstants.ATTRIBUTE_COLOR + ";\n" +
" " + ShaderProgramConstants.VARYING_TEXTURECOORDINATES + " = " + ShaderProgramConstants.ATTRIBUTE_TEXTURECOORDINATES + ";\n" +
" gl_Position = " + ShaderProgramConstants.UNIFORM_MODELVIEWPROJECTIONMATRIX + " * " + ShaderProgramConstants.ATTRIBUTE_POSITION + ";\n" +
"}"
I am new to open GL and have just started doing research on vertex shaders, so any suggestion or tip would be much appreciated.
EDIT: The problem I experience, is that the pixels from my texture get deformed when scaled. Normal textures look fine, but when they are scaled using the scaleM command on the 4x4 Matrix (Model view matrix), then it looks like there are two columns or two rows of the same pixels in random rows and columns.
Turns out the scale factor was causing the distortion. All I had to do was make sure that each pixel in the texture had the same amount of pixels on the display, and the distortions disappeared.
Related
I want to get length scale, length unit, energy scale, and energy unit from an EELS map data by DM script
source.ImageGetDimensionCalibration(0, sOrig, sScale, sUnit, 0)
source.ImageGetDimensionCalibration(2, eOrig, eScale, eUnit, 0)
The above codes did not work, it always make the energy unit with 1eV
For example, an EELS data with dispersion 0.9 ev/pixel, or 0.5 ev/pixel, and the energy range from 0 to 400, and the EELS map is 10nm x8nm, I need to get all this information with DM script.
Now the bug of my code is it always count the disepersion is 1 ev/pixel
Any suggestions, thanks
The following script will hopefully clear up any questions:
void PrintCalibrations(image source)
{
number nDim = source.ImageGetNumDimensions()
result("\n '[" + source.ImageGetLabel() +"]:"+ source.ImageGetName() +"' calibrations:")
result("\n Data has " + nDim + " dimensions.")
for( number d=0; d<nDim; d++ )
{
string unit_dim
number scale_dim, origin_dim
source.ImageGetDimensionCalibration(d, origin_dim, scale_dim, unit_dim, 0)
result("\n\t Dimension #"+d+": scale = " + scale_dim + " \t origin = " + origin_dim + " \t [" + unit_dim + "]" )
}
}
// Pick your data by image letter!
Image SIdata_3D := B
Image PickerSpectrum_1D := A
Image elementalMap_2D := D
ClearResults()
PickerSpectrum_1D.PrintCalibrations()
elementalMap_2D.PrintCalibrations()
SIdata_3D.PrintCalibrations()
Applied to a test data set:
For a line profile (curve), I want to reach that list all X coordinates that corresponding a Y coordinate by given this Y coordinate. And I could get the minimum and maximum values of these x coordinates. Here supposed I want to list all the X coordinates corresponding y=8, is this correct or any other better way? Thx
Number minx, maxx
Image front=:getfrontimage()
GetSize( front, xsize, ysize )
for (i=0; i<xsize; i++)
{
x= getpixel(front, i, 8)
minx=min(x)
maxx=max(x)
}
You script becomes wrong when you use the min and max, because you can not get a minimum/maximum of a single value (or rather, it is always that value). What you want to do is likely:
image spec := RealImage("Test",4,100)
spec = trunc(Random()*10)
number v = 8
ClearResults()
number nCh = spec.ImageGetDimensionSize(0)
for( number i=0; i<nCh; i++)
{
if( v == sum(spec[i,0]) )
Result("\n Value "+ v +" # " + i )
}
(The sum() is needed here a a trick to convert an image-expression to a single value.)
However, going pixel-by-pixel in script can be slow. Whenever possible, try to code with image-expressions, because they are much faster (for big images).
I therefore often utilize a trick: I threshold an image for the value I search for, and then iterate over that mask as long as it is not all-zero. The max(img,x,y) command will return the first maximum if there are multiple, so I get an ordered list.
image spec := RealImage("Test",4,100)
spec = trunc(Random()*10)
spec.ShowImage()
number v = 8
image mask = (spec==v)?1:0
ClearResults()
while( 0<sum(mask) )
{
number x,y
max(mask,x,y)
Result("\n Value " + v +" # " + x )
mask[x,0]=0
}
Edit: Answering the question of the comment below.
This is how one gets the ZLP maximum (position and value) from a line-profile in calibrated values.
Precursor: DM contains all data as simple arrays and values (real or integer). These are the real data and unrelated to any calibrations. You see these values if you toggle the "calibration" checkbox off in the Image Status palette:
These are the values all script commands etc. will use, i.e. positions are always indices (starting from 0) and values are the raw numeric values stored.
These images or spectra are calibrated by defining an origin and scale (and unit) for each dimensional axis as well as the intensity (=value). These triplets of values can be found in the image display info of data:
Only when the "Show calibrated values" checkbox is checked, is the data displayed in calibrated values. However, the real values remain unchanged. Just the scale/origin values are used to convert the numbers.
If you want to use a script to use calibrated values, then you have to perform the same conversions in you script yourself.
Here is the example:
image spectrum := GetFrontImage()
number xScale = spectrum.ImageGetDimensionScale(0) // 0 for X dimension
number xOrigin = spectrum.ImageGetDimensionOrigin(0)
string xUnit = spectrum.ImageGetDimensionUnitString(0)
number iScale = spectrum.ImageGetIntensityScale()
number iOrigin = spectrum.ImageGetIntensityOrigin()
string iUnit = spectrum.ImageGetIntensityUnitString()
string info = "\n"
info += "Image ["+spectrum.ImageGetLabel()+"]:"
info += "\n\t Dimension calibration: nCh * " + xScale + " + " + xOrigin + " [" + xUnit + "]"
info += "\n\t Intensity calibration: (value - " + iOrigin + ") * " + iScale +" [" + iUnit + "]"
Result(info)
// Find ZLP maximum (uncalibrated values)
number maxP_ch, dummy, maxV_raw
maxV_raw = max(spectrum,maxP_ch,dummy)
info = "\n"
info += "\n\t The maximum position is at channel index: " + maxP_ch
info += "\n\t The maximum Value at maximum position is: " + maxV_raw
Result(info)
number maxP_cal = xOrigin + xScale * maxP_ch
number maxV_cal = (maxV_raw - iOrigin) * iScale
info = "\n"
info += "\n\t The maximum position is at : " + maxP_cal
info += "\n\t The maximum Value is : " + maxV_cal
Result(info)
Note the different calibration formulas between dimensional calibration and intensity calibration!
For some reason I get title at the bottom of the plot. How do I change its position to the top?
p1=ggplot(data, aes(x=var1, y=var2, color=data$var3, shape=data$var3)) +
geom_point() +
geom_smooth(method=lm, se=FALSE, fullrange=TRUE) +
labs(title=“Main title”) +
scale_x_continuous(limits=c(-5, 5),
labels=c("0.01","0.08","1.0","12.2","148.4")) +
scale_y_continuous(name="Y axis label", limits=c(0,140)) +
theme_bw() +
theme(legend.position="none")
p1
For a 3D dataset, GMS 3 will assign a slice tool to navigate the 3rd dimension - typically used to navigate EELS and EDS SIs.
For a 4D dataset, this is not the case - in fact, no slider appears at all, nevermind two.
I would like to create a small GUI with sliders for each additional dimension beyond the two "image" dimensions, but I'm not sure what command is used to change the visible slice on the screen. I'd appreciate it if someone could help.
As for creating a small 4D image, it can be done with the collowing code:
image A = IntegerImage("", 2, 0, 16, 16, 16, 16)
ShowImage(A)
The slice tool for 4D is a licensed tool - then it works out of the box.
But if you want to build a proxy by script, you can do this.
The commands for getting/setting the "displayed" slices in a 3D and 4D display are the following:
void ImageDisplayGetDisplayedLayers( ImageDisplay imgDisp, NumberVariable start, NumberVariable end )
void ImageDisplayGetDisplayedLayers( ImageDisplay imgDisp, NumberVariable start1, NumberVariable end1, NumberVariable start2, NumberVariable end2 )
void ImageDisplaySetDisplayedLayers( ImageDisplay imgDisp, Number start, Number end )
void ImageDisplaySetDisplayedLayers( ImageDisplay imgDisp, Number start1, Number end1, Number start2, Number end2 )
Here is an example of how to use them:
image Img := realimage("4D Data", 4, 3, 5, 7, 9 )
Img = 10000 + idimindex(0) + 10 * idimindex(1) + 100 * idimindex(2) + 1000 * idimindex(3)
Img.ShowImage()
imageDisplay disp = A.ImageGetImageDisplay(0)
number start1,start2
number end1,end2
disp.ImageDisplayGetDisplayedLayers(start1,end1,start2,end2)
ClearResults()
Result( "Current Display Sliders are:" )
Result( "\n 3rd dim:" + start1 + " - " + end1 )
Result( "\n 4th dim:" + start2 + " - " + end2 )
OKDialog( "Now setting..." )
disp.ImageDisplaySetDisplayedLayers(start1,end1,start2+2,end2+2)
disp.ImageDisplayGetDisplayedLayers(start1,end1,start2,end2)
Result( "Current Display Sliders are now:" )
Result( "\n 3rd dim:" + start1 + " - " + end1 )
Result( "\n 4th dim:" + start2 + " - " + end2 )
However, I have just checked the free version of GMS 3.2.2 as downloaded from Gatan's webpage.
If you use the SI Viewer license (which is free), then the 4D slice-tool works just fine. As does the 4D picker-tool, apparently.
Can someone smarter than me take a look at this. I'm trying to implement a Bezier curve algorithm I found here in objective-c.
The output is way wrong. I think I converted the code correctly so either the original was wrong or was not ment to be used like this... If I use the built in NSBezierPath the curve looks great but I can't use the built in NSBezierPath.
NSBezierPath example
NSBezierPath *bezierPath = [[NSBezierPath alloc] init];
[bezierPath setLineWidth:1.0f];
[bezierPath moveToPoint:NSMakePoint(x1, y1)];
[bezierPath curveToPoint:NSMakePoint(x4, y4) controlPoint1:NSMakePoint(x2, y2) controlPoint2:NSMakePoint(x3, y3)];
My code trying to draw a bezier curve
- (void)drawBezierFrom:(NSPoint)from to:(NSPoint)to controlA:(NSPoint)a controlB:(NSPoint)b color:(NSUInteger)color
{
float qx, qy;
float q1, q2, q3, q4;
int plotx, ploty;
float t = 0.0;
while (t <= 1)
{
q1 = t*t*t*-1 + t*t*3 + t*-3 + 1;
q2 = t*t*t*3 + t*t*-6 + t*3;
q3 = t*t*t*-3 + t*t*3;
q4 = t*t*t;
qx = q1*from.x + q2*to.x * q3*a.x + q4*b.x;
qy = q1*from.y + q2*to.y * q3*a.y + q4*b.y;
plotx = round(qx);
ploty = round(qy);
[self drawPixelColor:color atX:plotx y:ploty];
t = t + 0.003;
}
}
Edit
See Bezier curve algorithm in objective-c needs a tweak for a completed functional Bezier Curve method.
I used this Bezier function with my xy plotter and found a small error with the 'to'.
The to.x to.y and b.x b.y need to be switched so that the pen starts at from and ends at to.
qx = q1*from.x + q2*a.x + q3*b.x + q4*to.x;
qy = q1*from.y + q2*a.y + q3*b.y + q4*to.y;
It looks to me like you have the wrong coefficients with each point and that one of your adds became a multiply. I think what you want is this:
qx = q1*from.x + q2*a.x + q3*to.x + q4*b.x;
qy = q1*from.y + q2*a.y + q3*to.y + q4*b.y;