Showing posts with label cs513. Show all posts
Showing posts with label cs513. Show all posts

Monday, November 30, 2009

Dilated seams

Seams are starting to look better:
I've switched back to GL_NEAREST for the texture filtering and implemented my own dilating filter that uses the max value from the texels in a 3x3 area as the fragment color. I'm not sure if this is correct, but I'll move ahead as if it is.

Continuing seam problems

I'm continuing to have problems with seams.
In this case, Frank is texture baked as a flat red image. I believe that all of the seams should show up as the same color that was used for Frank, ie, the seams should all be red.

In this case, the fragment shader is set up to discover when the resulting color is black and set the seam color to so darker red so that it is obvious what is missing. It is easy to see that a bunch of the information is not transported across to the matching seam.

It looks to me like the tex coords for grabbing the data from the other side of the seam are wrong or are mapping to black spaces.

Here's my code:

//----------------------------------------------------------------------
// Find seams in the object
//----------------------------------------------------------------------
void OBJModel::findSeams(void)
{
// Seams lie along triangle edges. For each triangle, there are
// three possible seams (v0,v1), (v0,v2) and (v1,v2)
//
// Those lines might be seams if each of the vertices has more than
// one texture coordinate.
for(GLuint tri = 0; tri < _triangles.size(); tri++)
{
// Make a convenient copy of the vertex and texcoord indices
GLuint v[3];
GLuint t[3];

for(int i = 0; i < 3; i++)
{
v[i] = _triangles[tri].vertex(i);
t[i] = _triangles[tri].texCoord(i);
}

Seam sm;

// Find any matching seams for line segment (v0, v1)
sm.v0 = v[0]; sm.v1 = v[1]; sm.t0a = t[0]; sm.t1a = t[1];
findMatchingSeams(sm, tri);

// Find any matching seams for line segment (v0, v2)
sm.v0 = v[0]; sm.v1 = v[2]; sm.t0a = t[0]; sm.t1a = t[2];
findMatchingSeams(sm, tri);

// Find any matching seams for line segment (v1, v2)
sm.v0 = v[1]; sm.v1 = v[2]; sm.t0a = t[1]; sm.t1a = t[2];
findMatchingSeams(sm, tri);
}

cout << "Seams: " << _seams.size() << endl;
cout << "Duplicate vertices: " << _duplicateVertices.size() << endl;
}


//----------------------------------------------------------------------
// Find any matching seams for a line segment
//----------------------------------------------------------------------
void OBJModel::findMatchingSeams(Seam sm0, GLuint noTri)
{
// Both of the vertices need to have more than 1 tex coord
// for this to be a seam
if(numTexCoords(sm0.v0) <= 1 || numTexCoords(sm0.v1 <= 1))
return;

// Find triangles with the same vertex indices
for(GLuint tri = 0; tri < _triangles.size(); tri++)
{
// If this triangle contains these two vertices
if(tri != noTri &&
_triangles[tri].hasVertex(sm0.v0) &&
_triangles[tri].hasVertex(sm0.v1))
{
// Make a copy of the potential seam
Seam sm(sm0);
bool found0 = false;
bool found1 = false;

// Find the tex coords in the matching seam
for(int i = 0; i < 3; i++)
{
// If vertex index 0 matches vertex index i,
// get the texture coord on the other side of the seam
if(sm.v0 == _triangles[tri].vertex(i))
{
found0 = true;
sm.t0b = _triangles[tri].texCoord(i);
}

// If vertex index 1 matches vertex index i,
// get the texture coord on the other side of the seam
if(sm.v1 == _triangles[tri].vertex(i))
{
found1 = true;
sm.t1b = _triangles[tri].texCoord(i);
}
}

// This shouldn't happen and in practice I haven't seen it happen, but
// check anyways
if(!found0 && !found1)
{
cout << "Found a seam but no matching texcoords" << endl;
}

// If the tex coords on the other triangle are exactly the same,
// then this isn't a seam. Removing this check results in an image
// that appears exactly the same as the one above
if(!(sm.t0a == sm.t0b && sm.t1a == sm.t1b))
{
// Add the duplicate vertices
_duplicateVertices.insert(sm.v0);
_duplicateVertices.insert(sm.v1);

// Add this seam to the list
_seams.push_back(sm);
}
}
}
}

Saturday, November 28, 2009

Friday, November 27, 2009

Duplicate vertices

Drawing the seams w/ duplicate vertices:
What's up with those duplicate vertices all over the place? They should be on the seams.

Saturday, November 14, 2009

Assignment 5.2

The shadowmap rendered in texture space but blurred using the baked position map for the weights:

The background image that can be seen through Frank and rendered in texture space and blurred:

And here those two images are composited on Frank:

I have to say, that image really sucks. Things aren't being composited together correctly and the seams are just awful. Biggest piece of crap image I've produced yet. Seriously. I need to step up my game. The only reason I'm turning in such a POS image is because I've spent waaay too much time on this class and I'm going to burn out. I need to save something for the remaining assignments. Normally I'd just keep cranking until I got something that looked halfway decent.

Here's one clue as to some of the problems I'm having:

This uses the dot product of the normal and light direction to shade the unshadowed parts. Note the difference in the shadow boundary between the part that is shadowed via the shadow map and the die off of the cosine term for the unshadowed part.

Definitely something that I need to fix.

However, I'll be working on seams for the rest of the day and hope that ways to make Frank look better magically pop into my head while working on something else. It's amazing how often tricks like that work.

The blurring was done using a weighted blur that was based on position in space. 9 texels are used in the blur and the distance from the center is calculated. That distance is fed into an exponential, the weights are summed and the center texel is weighted with the remaining weight. This way everything sums to 1 and light energy is conserved.

Download, build and run:

wget http://riskybacon.com/classes/cs513/assign5.2/assign5.2.tar.bz2
tar jxf assign5.2.tar.bz2
cd assign5.2/assign5.2
make
./test

Click and drag with the mouse to rotate the camera around Frank.

Tuesday, October 6, 2009

Assignment #4.2



Movies: 480p (12.1 MB) 720p (18.2MB).

Download source code here

To build:
wget http://riskybacon.com/classes/cs513/assign4.2/assign4.2.tar.bz2
tar jxf assign4.2.tar.bz2
cd assign4.2/ps
make
./ps

Press 'q' to quit, click and drag the mouse to move the camera.

This was built under Mac OS 10.5.8 and requires Cg and a Cg capable card to run the shaders. Machine: MacBook Pro 17", 2.4GHz, 4GB of RAM, GeForce 8600M GT, 256MB Ram.


For this assignment, the particle system from the previous assignment has been changed to run on the GPU. 4 source textures are sent to the fragment shader for the update pass: initial position, initial velocity, current position and current velocity. The fragment shaders outputs two colors to multiple render targets: the new position and the new velocity. Multiple render targets are used to get both textures written to in a single pass.

There was a lot of trickiness regarding OpenGL state. I never really appreciated just how much state is kept. Looking at the OpenGL spec cleared up a lot of problems as it is fairly clear about what state is kept with things like framebuffer objects and what things will case their state to become invalid.

The final stumbling point for me was changing the bound texture for unit 0 in the update pass, not realizing it and having that texture be used for rendering the particle system. This usually resulted in seeing nothing. At the end of the update pass, it was critical to restore as much state as possible. Alternatively, the render pass could have been more thorough about setting its required state.

In the first step, I made the particles look much nicer. In the previous assignment, the particles had black boxes around them. Blending was clearly not looking right. To fix this, the depth mask was turned off when rendering the particle system. This was a very simple fix and made the particle system look much better.

The next step was to back out vertex buffer objects and compare the timings between plain vertex arrays and vbos:

The following two tests used 5000 particles:
Feature added Frames per second
vertex arrays 61.25
vertex buffer objects 61.5


This didn't make any difference. I suspect that this is because the VBO is being pushed out to the GPU for every frame.

The next step was to move the simulation from the CPU to the GPU. First, I altered the CPU based program to use a 4th order Runga-Kutta method to find the positions of the particles and time it.

Next, the incredibly simple step of moving the simulation to the GPU was undertaken. It turns out that this was very, very hard for me. I'm not too happy with the resulting simulation. It looks different than the one on the CPU and doesn't feel quite right. It was nice to see a very large speedup.


Particles CPU (FPS) GPU (FPS) Speedup
4096 85.2014 397.667 4.7
16384 21.8503 228.354 10.5
65536 5.47826 79.6116 14.5
262144 1.36898 14.6308 12.1
589824 0.609053 5.7222 9.4
1048576 0.345382 3.07792 8.9


The next step was to add an opaque object to the scene and make sure that it rendered properly. As you can see from the screen shot and movie, it worked out.

I'm not very happy with the quality of the simulation, so I will be continuing to work on it.

Monday, October 5, 2009

Assignment #4

Simple particle system:

Movie of particle system




Program built on a MacBook Pro running OS X Leopard with an NVidia card:

wget http://cs.unm.edu/~jbowles/cs513/assign4-jbowles.tar.bz2
tar jxf assign4-jbowles.tar.bz2
cd assign4-jbowles/ps
make
./ps

You can move the view around by holding down the left button and dragging. Shaders can be reloaded by pressing 'r'. You can quit with 'Q' or escape.

This particle system models particles being launched out of a gravity well at just over escape velocity. The particles make a couple of passes past the gravity well and then escape.

Once they've reached a reasonable distance away, the particle is reinitialized and the process starts over.

The particles are modeled as point sprites and passed to the GPU in a vertex buffer object.

The vertex shader does the usual: it tranforms the model coordinates into world space and leaves the texture coordinates alone. The vertex shader also calculate a luminance value based on the distance of the particle from the gravity well. This value is passed on TEXCOORD1 to the pipeline.

The fragment shader uses an exponential function to determine the alpha component of the fragment. The input to the exponential is the distance of the fragment from the center of the point sprite.

The color (not the alpha) of the fragment is determined by the distance of the point sprite from the gravity well. As the sprite gets farther from the well, it "cools off" and the red component goes to zero.

It is interesting to see how ordering has an effect on the alpha blending of the particles. Since these particles are not ordered, the blending is not always correct. I'm looking forward to putting the particles onto the GPU and sorting them there.

On my MacBook Pro, this ran at about 60 FPS when using 1, 20, 2000, or 100000 particles. I suspect that this is because I'm using synchronized swap buffers. When I remove this constraint, FPS goes up to 600 with 200 particles. If I use 20000 particles, the frame rate is about 100 without synchronized buffers.

Thursday, September 24, 2009

Bump mapping




This is the first step in completing assignment #3. The height map was created using difference clouds in photoshop. A fragment shader was written that computes the normal map. This is rendered using a frame buffer object. The normal map is attached to a texture and fed into another shader that lights the models using the normals from the normal map.

In the upper right corner of the scene, the normal map is displayed on a textured quad.

Monday, September 14, 2009

Shadow mapping deformation

I was noticing that the shadow is deformed. It appears that the order that the vertices are sent is important. After paying very careful attention to vertex order and switching from a GL_QUAD to a GL_TRIANGLE_STRIP, the deformation has mostly disappeared.

Something that is confusing me is when I send over a rectangular plane and not a square plane, the shadow seems deformed.

I'm not sure why this is happening. Here are the screen shots:

Square plane, shadow looks correct to me:

Rectangular plane, deformed shadow:

Thursday, September 10, 2009

Assignment #2

CS513, Assignment #2

Source is here

Images can be clicked on for a larger view.

Scene viewed normally from the camera:



Scene viewed from the light source:



How to build and run:

tar jcf jbowles-assign2.tar.bz2
cd jbowles-assign2/shadowmap
make
./shadowmap

Press 'c' to toggle light/eye camera
Press space to pause/unpause teapot rotation
Press 'r' to reload shaders

Problems and fixes:

The shadow is not in the correct position. I suspect that this is due to the problem that Joe described with the light projection and view matrices not being set up right. When the view is from the light position, everything looks correct to me, but there seems to be some subtle issue. You can see this in the light view screen cap. The shadow should not be visible.

I'm not sure what the fix is in this case. I'll keep looking into this.

Transforming the model coordinate into light texture space was problematic. Initially I was just multiplying the untransformed coordinate in the vertex shader by the light model view projection matrix.

Solution: perspective divide and pre multiply the MVP with a clip to texture matrix. The clip to texture matrix moves the vertex into the light's canonical view volume.

Row major vs column major storage of matrices was also a problem. I incorrectly assumed that the way OpenGL wants it matrices would be the same as the GPU. There is no reason why this assumption should be true and it's clear from the Cg examples that this is not the case. While I was getting a lot of the math correct on the CPU side,
I was sending the GPU matrices that needed to be transposed.

I plan on changing my matrix class to store everything row major. If I need to load one of my matrices into the OpenGL state, then I'll transpose it. Right now I transpose all matrices before sending them to the GPU because I store them in column major order.

Thursday, August 27, 2009

Cg shader using XCode

No code to post, I'm just happy that I'm able to load and use a Cg shader and OpenGL from within a project that is using OpenFrameworks under OS X.

Including the Cg framework from within the XCode project and specifying a full path to the Cg program were the tricks. I'd rather specify a relative path to the Cg program, but I would rather be learning Cg.