Gradient effect to pixels [Java] - java

How could I apply a gradient to something like this? Just got a solid colour.
for (int i = 0; i < screen.pixels.length; i++)
screen.pixels[i] = 0xff0000;

Solved the issue by getting the RGB values of hex codes, looping through the size of the rectangle that got the gradient, and interpolated between the two r, g, and b values.
float r = Color.decode(colourOne).getRed();
float g = Color.decode(colourOne).getGreen();
float b = Color.decode(colourOne).getBlue();
float r2 = Color.decode(colourTwo).getRed();
float g2 = Color.decode(colourTwo).getGreen();
float b2 = Color.decode(colourTwo).getBlue();
float interp, newR, newG, newB;
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
interp = (float) (x + y) / (float) (width + height);
newR = r * (1 - interp) + r2 * interp;
newG = g * (1 - interp) + g2 * interp;
newB = b * (1 - interp) + b2 * interp;
pixels[x + y * width] = (int) (Math.floor(newR) * 0x10000 + Math.floor(newG) * 0x100 + Math.floor(newB));
}
}

Related

bulge effects in java

I was researching bulge effect and I referenced this link below:
https://math.stackexchange.com/questions/266250/explanation-of-this-image-warping-bulge-filter-algorithm
the examples image are all nxn type, what if the image is mxn.
i tried to code but it always throws exception: row out of bounds.
my code as follows:
public static Picture positionalTransform(Picture picture) {
int w = picture.width();
int h = picture.height();
double X = 0;
double Y = 0;
Picture newPic = new Picture(w,h);
for(int x=0; x<w; x++){
for(int y=0; y<h; y++){
X = x - x/2;
Y = y - y/2;
double r = Math.hypot(X, Y);
double angle = Math.atan2(X, Y);
double rn = Math.pow(r, 2.5)/0.5;
X = (int) (rn * Math.sin(angle) + x/2);
Y = (int) (rn * Math.cos(angle) + y/2);
newPic.setColor((int)X, (int)Y, picture.getColor(x, y));
}
}
picture = newPic;
return picture;
}

Java hsb degrees or 255

I was wondering if when you call color.HSBtoRGB if the hue value would be entered as a range of 0-255, 0-1, 0-360? I am inquiring because I am trying to convert an edge angle to a color but it is only giving me blue or purple? can anyone explain what I am doing?
public void sobelGrey(){
this.greyScale();
double edgex;
double edgey;
Picture pi = new Picture(this.getWidth(), this.getHeight());
Picture tou = new Picture(this.getWidth(), this.getHeight());
Pixel[][] Y = pi.getPixels2D();
Pixel[][] X = tou.getPixels2D();
Pixel[][] h = this.getPixels2D();
for (int y = 1; y< X.length-1; y++){
for(int x= 1; x<X[1].length-1; x++){
edgex =
h[y-1][x-1].getRed() * -1 +
h[y][x-1].getRed() * -2+
h[y+1][x-1].getRed() * -1+
h[y-1][x+1].getRed() * 1 +
h[y][x+1].getRed() * 2+
h[y+1][x+1].getRed() * 1;
Y[y][x].setRed((int)Math.abs(edgex/2));
Y[y][x].setGreen((int)Math.abs(edgex/2));
Y[y][x].setBlue((int)Math.abs(edgex/2));
}
}
for (int y = 1; y< X.length-1; y++){
for(int x= 1; x<X[1].length-1; x++){
edgex =
h[y-1][x-1].getRed() * -1 +
h[y-1][x].getRed() * -2+
h[y-1][x+1].getRed() * -1+
h[y+1][x-1].getRed() * 1 +
h[y+1][x].getRed() * 2+
h[y+1][x+1].getRed() * 1;
X[y][x].setRed((int)Math.abs(edgex/2));
X[y][x].setGreen((int)Math.abs(edgex/2));
X[y][x].setBlue((int)Math.abs(edgex/2));
}
}
for (int y = 1; y< X.length-1; y++){
for(int x= 1; x<X[1].length-1; x++){
int x1 = (int) Math.sqrt(Math.pow(X[y][x].getRed(), 2) + Math.pow(X[y][x].getGreen(), 2) + Math.pow(X[y][x].getBlue(), 2));
int y1 = (int) Math.sqrt(Math.pow(Y[y][x].getRed(), 2) + Math.pow(Y[y][x].getGreen(), 2) + Math.pow(Y[y][x].getBlue(), 2));
int hr = (int) (200/(2*Math.PI)*(Math.tanh(y1/ (x1+.000000000000001))));
int rgb = Color.HSBtoRGB(hr/255, hr, (int) Math.sqrt(Math.pow(x1, 2) + Math.pow(y1, 2)));
Color fixed = new Color(rgb&0xFF*7/10, (rgb>>8)&0xFF*80/255/10, (rgb>>16)&0xFF*4/10);
if( !(Math.sqrt(Math.pow(x1, 2) + Math.pow(y1, 2))< 40))
h[y][x].setColor(fixed);
else
h[y][x].setColor(Color.black);
}
}
pi.explore();
tou.explore();
explore();
}
i am using a computer science AP image processing from Eimacs, and using the swan
You declared hr (and the other variables) to be an int. Then in Color.HSBtoRGB(hr/255, ... you divide an int by an int. For all values of hr below 255, the result will be 0.
Probably it is sufficient to divide by 255.0 to force a floating point division.

How to add n points between vertices when creating a polygon

Let's say I'm using the following code to create the vertices in a hexagon polygon:
hexagonPoints = new Array<Vector2>();
for (int a = 0; a < 6; a++)
{
float x = r * (float)Math.cos(a * 60 * Math.PI / 180f);
float y = r * (float)Math.sin(a * 60 * Math.PI / 180f);
hexagonPoints.add(new Vector2(x, y));
}
How can I add additional points along each side of the polygon, so that there are n additional points between each connecting set of vertices? All vertices must be equal distance (including the vertices that formed the initial shape). E.g. before:
. .
. .
After (where n = 1):
. . .
. .
. . .
edit: here's my current code based on Volker's suggestion:
float r = 3.0f;
int n = 1 + 2; // number of additional vertices between the main shape vertices
for (int a = 0; a < 6; a++)
{
float xe = r * (float)Math.cos(a * 60 * Math.PI / 180f);
float ye = r * (float)Math.sin(a * 60 * Math.PI / 180f);
if (a > 0)
{
for (int i = 1; i < n; ++i)
{
float xs = ((n - i) * hexagonPoints.get(a - 1).x + i * xe) / n;
float ys = ((n - i) * hexagonPoints.get(a - 1).y + i * ye) / n;
hexagonPoints.add(new Vector2(xs, ys));
}
}
hexagonPoints.add(new Vector2(xe, ye));
}
This plots the additional vertices, but they are not in the correct positions.
edit: seems this wasn't working because I wasn't taking into account the first vertex position.
Calculate the endpoints of each side as you are doing it already. Then introduce with an inner loop the additional splitting points.
for (int i=1; i<n: ++i)
{
float xs = ((n-i)*xb + i*xe)/n;
float ys = ((n-i)*yb + i*ye)/n;
hexagonPoints.add(new Vector(xs, ys));
}
hexagonPoints.add(new Vector(xe, ye));
where xb, yb is the beginning of a hexagon side and xe, ye the end.
Here's a working solution, based on Volker's suggestion:
int size = 6;
int npoints = 2;
int nsegs = npoints + 1;
float xb = r;
float yb = 0;
hexagonPoints.add(new Vector2(xb, yb));
for (int a = 1; a <= size; a++)
{
float xe = r * (float) Math.cos(a * 60 * Math.PI / 180f);
float ye = r * (float) Math.sin(a * 60 * Math.PI / 180f);
for (int i = 1; i < nsegs; ++i)
{
float xs = ((nsegs - i) * xb + i * xe) / nsegs;
float ys = ((nsegs - i) * yb + i * ye) / nsegs;
hexagonPoints.add(new Vector2(xs, ys));
}
if (a < size) hexagonPoints.add(new Vector2(xe, ye));
xb = xe;
yb = ye;
}

Coloring heightmap faces instead of vertices

I'm trying to create a heightmap colored by face, instead of vertex. For example, this is what I currently have:
But this is what I want:
I read that I have to split each vertex into multiple vertices, then index each separately for the triangles. I also know that blender has a function like this for its models (split vertices, or something?), but I'm not sure what kind of algorithm I would follow for this. This would be the last resort, because multiplying the amount of vertices in the mesh for no reason other than color doesn't seem efficient.
I also discovered something called flatshading (using the flat qualifier on the pixel color in the shaders), but it seems to only draw squares instead of triangles. Is there a way to make it shade triangles?
For reference, this is my current heightmap generation code:
public class HeightMap extends GameModel {
private static final float START_X = -0.5f;
private static final float START_Z = -0.5f;
private static final float REFLECTANCE = .1f;
public HeightMap(float minY, float maxY, float persistence, int width, int height, float spikeness) {
super(createMesh(minY, maxY, persistence, width, height, spikeness), REFLECTANCE);
}
protected static Mesh createMesh(final float minY, final float maxY, final float persistence, final int width,
final int height, float spikeness) {
SimplexNoise noise = new SimplexNoise(128, persistence, 2);// Utils.getRandom().nextInt());
float xStep = Math.abs(START_X * 2) / (width - 1);
float zStep = Math.abs(START_Z * 2) / (height - 1);
List<Float> positions = new ArrayList<>();
List<Integer> indices = new ArrayList<>();
for (int z = 0; z < height; z++) {
for (int x = 0; x < width; x++) {
// scale from [-1, 1] to [minY, maxY]
float heightY = (float) ((noise.getNoise(x * xStep * spikeness, z * zStep * spikeness) + 1f) / 2
* (maxY - minY) + minY);
positions.add(START_X + x * xStep);
positions.add(heightY);
positions.add(START_Z + z * zStep);
// Create indices
if (x < width - 1 && z < height - 1) {
int leftTop = z * width + x;
int leftBottom = (z + 1) * width + x;
int rightBottom = (z + 1) * width + x + 1;
int rightTop = z * width + x + 1;
indices.add(leftTop);
indices.add(leftBottom);
indices.add(rightTop);
indices.add(rightTop);
indices.add(leftBottom);
indices.add(rightBottom);
}
}
}
float[] verticesArr = Utils.listToArray(positions);
Color c = new Color(147, 105, 59);
float[] colorArr = new float[positions.size()];
for (int i = 0; i < colorArr.length; i += 3) {
float brightness = (Utils.getRandom().nextFloat() - 0.5f) * 0.5f;
colorArr[i] = (float) c.getRed() / 255f + brightness;
colorArr[i + 1] = (float) c.getGreen() / 255f + brightness;
colorArr[i + 2] = (float) c.getBlue() / 255f + brightness;
}
int[] indicesArr = indices.stream().mapToInt((i) -> i).toArray();
float[] normalArr = calcNormals(verticesArr, width, height);
return new Mesh(verticesArr, colorArr, normalArr, indicesArr);
}
private static float[] calcNormals(float[] posArr, int width, int height) {
Vector3f v0 = new Vector3f();
Vector3f v1 = new Vector3f();
Vector3f v2 = new Vector3f();
Vector3f v3 = new Vector3f();
Vector3f v4 = new Vector3f();
Vector3f v12 = new Vector3f();
Vector3f v23 = new Vector3f();
Vector3f v34 = new Vector3f();
Vector3f v41 = new Vector3f();
List<Float> normals = new ArrayList<>();
Vector3f normal = new Vector3f();
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (row > 0 && row < height - 1 && col > 0 && col < width - 1) {
int i0 = row * width * 3 + col * 3;
v0.x = posArr[i0];
v0.y = posArr[i0 + 1];
v0.z = posArr[i0 + 2];
int i1 = row * width * 3 + (col - 1) * 3;
v1.x = posArr[i1];
v1.y = posArr[i1 + 1];
v1.z = posArr[i1 + 2];
v1 = v1.sub(v0);
int i2 = (row + 1) * width * 3 + col * 3;
v2.x = posArr[i2];
v2.y = posArr[i2 + 1];
v2.z = posArr[i2 + 2];
v2 = v2.sub(v0);
int i3 = (row) * width * 3 + (col + 1) * 3;
v3.x = posArr[i3];
v3.y = posArr[i3 + 1];
v3.z = posArr[i3 + 2];
v3 = v3.sub(v0);
int i4 = (row - 1) * width * 3 + col * 3;
v4.x = posArr[i4];
v4.y = posArr[i4 + 1];
v4.z = posArr[i4 + 2];
v4 = v4.sub(v0);
v1.cross(v2, v12);
v12.normalize();
v2.cross(v3, v23);
v23.normalize();
v3.cross(v4, v34);
v34.normalize();
v4.cross(v1, v41);
v41.normalize();
normal = v12.add(v23).add(v34).add(v41);
normal.normalize();
} else {
normal.x = 0;
normal.y = 1;
normal.z = 0;
}
normal.normalize();
normals.add(normal.x);
normals.add(normal.y);
normals.add(normal.z);
}
}
return Utils.listToArray(normals);
}
}
Edit
I've tried doing a couple things. I tried rearranging the indices with flat shading, but that didn't give me the look I wanted. I tried using a uniform vec3 colors and indexing it with gl_VertexID or gl_InstanceID (I'm not entirely sure the difference), but I couldn't get the arrays to compile.
Here is the github repo, by the way.
flat qualified fragment shader inputs will receive the same value for the same primitive. In your case, a triangle.
Of course, a triangle is composed of 3 vertices. And if the vertex shaders output 3 different values, how does the fragment shader know which value to get?
This comes down to what is called the "provoking vertex." When you render, you specify a particular primitive to use in your glDraw* call (GL_TRIANGLE_STRIP, GL_TRIANGLES, etc). These primitive types will generate a number of base primitives (ie: single triangle), based on how many vertices you provided.
When a base primitive is generated, one of the vertices in that base primitive is said to be the "provoking vertex". It is that vertex's data that is used for all flat parameters.
The reason you're seeing what you are seeing is because the two adjacent triangles just happen to be using the same provoking vertex. Your mesh is smooth, so two adjacent triangles share 2 vertices. Your mesh generation just so happens to be generating a mesh such that the provoking vertex for each triangle is shared between them. Which means that the two triangles will get the same flat value.
You will need to adjust your index list or otherwise alter your mesh generation so that this doesn't happen. Or you can just divide your mesh into individual triangles; that's probably much easier.
As a final resort, I just duplicated the vertices, and it seems to work. I haven't been able to profile it to see if it makes a big performance drop. I'd be open to any other suggestions!
for (int z = 0; z < height; z++) {
for (int x = 0; x < width; x++) {
// scale from [-1, 1] to [minY, maxY]
float heightY = (float) ((noise.getNoise(x * xStep * spikeness, z * zStep * spikeness) + 1f) / 2
* (maxY - minY) + minY);
positions.add(START_X + x * xStep);
positions.add(heightY);
positions.add(START_Z + z * zStep);
positions.add(START_X + x * xStep);
positions.add(heightY);
positions.add(START_Z + z * zStep);
}
}
for (int z = 0; z < height - 1; z++) {
for (int x = 0; x < width - 1; x++) {
int leftTop = z * width + x;
int leftBottom = (z + 1) * width + x;
int rightBottom = (z + 1) * width + x + 1;
int rightTop = z * width + x + 1;
indices.add(2 * leftTop);
indices.add(2 * leftBottom);
indices.add(2 * rightTop);
indices.add(2 * rightTop + 1);
indices.add(2 * leftBottom + 1);
indices.add(2 * rightBottom + 1);
}
}

Java heightmap using lwjgl

I have coded a heightmap but it seems to lag the client. I just don't know how to increase the fps. I get about 3-6fps with the heightmap. Im using a quite large bmp for the heightmap, I think its 1024x1024. When i use a smaller on its fine, maybe im just not using the code effectively. Is there a better way to code this heightmap or did I just code it wrong. It is my first time I have worked on a heightmap. Thanks
public class HeightMap {
private final float xScale, yScale, zScale;
private float[][] heightMap;
private FloatBuffer vertices, normals, texCoords;
private IntBuffer indices;
private Vector3f[] verticesArray, normalsArray;
private int[] indicesArray;
private int width;
private int height;
public float getHeight(int x, int y) {
return heightMap[x][y] * yScale;
}
public HeightMap(String path, int resolution) {
heightMap = loadHeightmap("heightmap.bmp");
xScale = 1000f / resolution;
yScale = 8;
zScale = 1000f / resolution;
verticesArray = new Vector3f[width * height];
vertices = BufferUtils.createFloatBuffer(3 * width * height);
texCoords = BufferUtils.createFloatBuffer(2 * width * height);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
final int pos = height * x + y;
final Vector3f vertex = new Vector3f(xScale * x, yScale * heightMap[x][y], zScale * y);
verticesArray[pos] = vertex;
vertex.store(vertices);
texCoords.put(x / (float) width);
texCoords.put(y / (float) height);
}
}
vertices.flip();
texCoords.flip();
normalsArray = new Vector3f[height * width];
normals = BufferUtils.createFloatBuffer(3 * width * height);
final float xzScale = xScale;
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
final int nextX = x < width - 1 ? x + 1 : x;
final int prevX = x > 0 ? x - 1 : x;
float sx = heightMap[nextX][y] - heightMap[prevX][y];
if (x == 0 || x == width - 1) {
sx *= 2;
}
final int nextY = y < height - 1 ? y + 1 : y;
final int prevY = y > 0 ? y - 1 : y;
float sy = heightMap[x][nextY] - heightMap[x][prevY];
if (y == 0 || y == height - 1) {
sy *= 2;
}
final Vector3f normal = new Vector3f(-sx * yScale, 2 * xzScale, sy * yScale).normalise(null);
normalsArray[height * x + y] = normal;
normal.store(normals);
}
}
normals.flip();
indicesArray = new int[6 * (height - 1) * (width - 1)];
indices = BufferUtils.createIntBuffer(6 * (width - 1) * (height - 1));
for (int i = 0; i < width - 1; i++) {
for (int j = 0; j < height - 1; j++) {
int pos = (height - 1) * i + j;
indices.put(height * i + j);
indices.put(height * (i + 1) + j);
indices.put(height * (i + 1) + (j + 1));
indicesArray[6 * pos] = height * i + j;
indicesArray[6 * pos + 1] = height * (i + 1) + j;
indicesArray[6 * pos + 2] = height * (i + 1) + (j + 1);
indices.put(height * i + j);
indices.put(height * i + (j + 1));
indices.put(height * (i + 1) + (j + 1));
indicesArray[6 * pos + 3] = height * i + j;
indicesArray[6 * pos + 4] = height * i + (j + 1);
indicesArray[6 * pos + 5] = height * (i + 1) + (j + 1);
}
}
indices.flip();
}
private float[][] loadHeightmap(String fileName) {
try {
BufferedImage img = ImageIO.read(ResourceLoader.getResourceAsStream(fileName));
width = img.getWidth();
height = img.getHeight();
float[][] heightMap = new float[width][height];
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
heightMap[x][y] = 0xFF & img.getRGB(x, y);
}
}
return heightMap;
} catch (IOException e) {
System.out.println("Nincs meg a heightmap!");
return null;
}
}
public void render() {
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glNormalPointer(0, normals);
glVertexPointer(3, 0, vertices);
glTexCoordPointer(2, 0, texCoords);
glDrawElements(GL_TRIANGLE_STRIP, indices);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
}
Sorry to bring up an old topic, however i see a lot of people ask this:
Use a display list, instead of re-making the heightmap every time.
TheCodingUniverse has a good tutorial on how to do this.

Categories

Resources