Categories
Computer Graphics

Falloff Gradients

So I'm sitting there in my office at home, coding up Anton's Triangle Tutorial program in an effort to learn OpenGL. While I do this, the COVID-19 virus is busy multiplying in the world and getting a lot of people sick. But since I'm quarantined, I keep myself busy translating Anton's C/C++ code into Java. I'm using Java/Scala for my project because that's where I've spent of the majority of time in my career for the past ten years and I was curious how far I can push the platform.

In Java I started to use the Lightweight Java Game Library (lwjgl) which has a very good OpenGL bindings. Small note that the light library I'm writing on top of lwjgl is written in pure Java, but most of my client code is written in Scala. The lwjgl bindings are good because they take advantage of a few features of the JVM which make it straightforward to work with native libraries.

The first of these features is Java NIO. A few weeks ago I went through Jenkov.com's Java NIO Tutorials since I was a bit rusty on Java NIO. Using Java NIO you can expose native memory to the native OpenGL API's through a safe JVM interface, which is exactly what the native OpenGL library requires.

The second feature was introduced in Java 5 in 2004, static imports. Using Static imports you can simulate Standard C/C++ #include directive, which exposes variables, functions, and classes to your default namespace without any object or static class qualifiers. So, OpenGl code in C++ like this:

while(!glfwWindowShouldClose(window)) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glUseProgram(shader_prog);
  glBindVertexArray(vao);
  glDrawArrays(GL_TRIANGLES, 0, 3);
  glfwPollEvents();
  glfwSwapBuffers(window);
}

Looks like this in Java. Yes, they are identical.

while(!glfwWindowShouldClose(window)) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glUseProgram(shader_prog);
    glBindVertexArray(vao);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glfwPollEvents();
    glfwSwapBuffers(window);
 }

Not all of the code is identical, however. Instead of this block of C++:

float points[] = {
   0.0f,  0.5f,  0.0f,
   0.5f, -0.5f,  0.0f,
  -0.5f, -0.5f,  0.0f
};

GLuint vbo = 0;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), points, GL_STATIC_DRAW);

Your Java code will look like this (assuming you have a similar definition for points:

# Scala
private val points = Array(
     0.0f,  0.75f, 0.0f,
     0.75f, -0.75f, 0.0f,
    -0.75f, -0.75f, 0.0f)

# Java
int vbo = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
Buffer buffer = BufferUtils.createFloatBuffer(data.length).put(data);
glBufferData(GL_ARRAY_BUFFER, (FloatBuffer)buffer.flip(), GL_STATIC_DRAW);

The program generates a color triangle and uses a mouse uniform to place a highlight over the cursor. Click on the image below to see the image in its full fidelity.

Default linear fall off gradient

The fall off is linear with the percentage of white being a linear fall off from 1->0 proportional with the distance from the mouse cursor over 300 pixels. The shader code looks like this:

#version 400

const float PI_2 = 1.57079632679489661923;

uniform vec2 u_resolution;
uniform vec2 u_mouse;

in vec3 color;
out vec4 frag_color;

#define FALLOFF (u_resolution.x / 16.0)

void main() {
    float distMouse = min(FALLOFF, distance(gl_FragCoord.xy, u_mouse));
    float lin_falloff = 1.0-(min(distMouse, FALLOFF) / FALLOFF);
    vec3 finalColor = mix(color, vec3(1.0,1.0,1.0), lin_falloff);
    frag_color = vec4(finalColor, 1.0);
}

In mathematical terms, it looks like this (generated from GNU Octave):

Which didn't look so bad in Octave, but in the original triangle image above the edge was too harsh and I wanted to soften it. I tried to square the falloff, yielding this curve:

But I felt the falloff dropped too abruptly. I decided to try cos(x). Notice how the center bulge is brighter:

Yet when viewed in OpenGL, the edge was still too abrupt, maybe even moreso!

Falloff based on cos(x)

So I decided to square cos(x) and notice t he beautiful S-curve I was looking for!

So I decided to generate a bunch of curves and try them all out:

Trying a bunch of curves.

In the end, none of the linear falloff variants pleased me and I went with cos(x)^2

This gave me the best central bulge and a smooth gradient that faded away without any noticeable edge. QED!

Categories
Computer Graphics

Computer Graphics

One of my long-time passions is computer graphics. Being nostalgic, I have been spending some time lately remembering how to do all of this stuff. I do most of my work on the JVM these days so I wanted to see what I could do with it.

So I hunted around and found a ton of options.

Here is a recording I made from n-body sample code in the aparapi-samples project on GitHub: https://github.com/Syncleus/aparapi-e... The first few seconds are a recording from the original sample code which was originally presented by Gary Frost from AMD at the 2010 Java One Conference. The last part of the video records numerous enhancements I made as I learned aparapi and OpenGL on the JVM.

My next post will talk about some of the API's I tried before I settled on one I liked. Enjoy!

Fin.

Categories
Hardware Programming

CPU Cooling

tl; dr;

Make sure your fans point the right way and you apply thermal paste properly.

When I bought my PC, I stuck am AMD 3900X 12/24 core processor in there and used the STOCK heat sink and fan. Out of the box, the processor ran anywhere from 40-60° C and I was pretty happy. Then I added a GPU and stick a few MORE fans into the case (at the top). When I was finished, the CPU was regularly overheating, spiking anywhere from 75-100° C.

This was annoying since my GPU was reading relatively cold 30-40° C.

I was ready to drop $200 for a water cooler, which I know would bring it down to 40° C (or less) even when in heavy use. But I obviously didn't want to spend the money on that since my upgrade list includes a second M.2 card and a second bank of 32GB of RAM.

I was talking to my son and he said that I'd put in t he top fans wrong. He said the best-practice is to draw air out from the top. I knew this was a best-practice too, but I decided against it because I wanted to see for myself and my intuition said that blowing cold outside air right onto the CPU heat sink was the way to go since those topside chassis fans are right next to the CPU heat sink.

Turns out I was probably wrong.

Another thing was to install those topside fans, I needed to re-set my CPU heat sink since it was "in the way". When I did this, I believe I didn't use enough thermal paste since I used the last bit of a syringe and had no more.

To make a long story short, I re-applied thermal paste and flipped the fans to blow out and now the PC idles around 45° C and heats to about 80° max under heavy load. That's still hot, but lowering peak temp by 20° C seems like a big deal for a minimal investment in thermal paste and a little elbow grease flipping those fans.

I wrote a simple Java program to saturate my CPU's. It just adds a counter so my gut tells me that lots of transistors in the CPU are unused and the program may not heat up the CPU even though the OS is reporting 100% utilization.  It's possible a program that either access more memory or more registers/logic gates on the die could theoretically cause the CPU to be busier and thus heat up more. If anyone knows about this, I'd love to learn more.

I may still spring for a water-cooler down the road, but if this configuration remains stable then I guess I'm happy with it.

Categories
Media

Space Render

From the archives: I made this sci-fi spaceship battle rendering in Bryce 4 way back in 2011.

Categories
Kung Fu Life Media

Easy Glass Buttons and the Greatness of Your Life

Way back in 2005 I wrote this blog post about how to create easy glass buttons in Adobe Illustrator. I remember this post being popular and still to this day it turns up as one of the top hits on Google search. I did this search Incognito just now, but curious if you see the same results or if the result is machine learned from my habits.

Go ahead, search, and click on the green button and see if it leads you to my post.

What I love about this post is that I was a relatively young 35-year old man who still had dreams about doing something big with technology and I strive to always retain that wonder. Now, almost 15 years later, I didn't do anything big by the standards I set for myself at that time, but I did make a living for my family, raised four gorgeous children, loved a beautiful wife, made some amazing friends, learned a lot of cool Kung Fu, and still manage to stay up to 3am bumping into walls wearing a new VR headset I have no idea how to use.

As I turn the corner on 50, I try to look at the young man who wrote that post and I try and see what made him tick. What I've come to realize is that it's not always the size or impact of your accomplishment and more about the journey. That's not to say I don't harbor disappointment at not doing more, or regret at not working harder. What I strive for is not to be so enveloped by disappointment that I throw my hands up, giving up and becoming a bitter old man. To this day, I still cling to that feeling I had when I was 35... that the best is yet to come. I hope I always feel that way, regardless of the quantifiable greatness of anything I do or don't do.