Showing posts with label OpenGL. Show all posts
Showing posts with label OpenGL. Show all posts
Tuesday, March 18, 2008
Another Demo Finished
Up to fixing up the user controls, I've finished my reflection/refraction demo. I've used hdr textures, but I haven't tone mapped them, so they're a bit bright. I'm going to do that in a future demo. At some point I'm going to turn these into a set of tutorials, but I might wait until OpenGL 3.0 finally arrives.
ImageIO OpenGL and Radiance .hdr Files
I promised to post my ImageIO code once I had things working, and now that it's working, I'm going to do just that. I just worked through the last bug I had in my texturing code.
If you're using ImageIO to read Radiance .hdr files, and you're getting garbage, check the type parameter you're passing to glTexImage2D. The Apple documentation concerning ImageIO and OpenGL uses the format GL_UNSIGNED_INT_8_8_8_8_REV. While .hdr files are floating point, its the REV you should take note of. The byte ordering of each R, G, B component is individually reversed between what ImageIO provides and OpenGL expects. Simply call glPixelStorei(GL_UNPACK_SWAP_BYTES,1) and things should look a bit more normal.
I hope this saves someone else a few minutes.
Boolean osx_CGImageSupportsFileFormat(std::string format) {
CFArrayRef imageFormats = CGImageSourceCopyTypeIdentifiers();
CFStringRef targetImageFormat = CFStringCreateWithCString( kCFAllocatorDefault, format.c_str(), kCFStringEncodingUTF8 );
CFRange imageFormatsRange = CFRangeMake( 0, CFArrayGetCount( imageFormats ) );
Boolean didContainFormat = CFArrayContainsValue(imageFormats, CFRangeMake(0, CFArrayGetCount(imageFormats)), targetImageFormat);
CFRelease(targetImageFormat);
CFRelease(imageFormats);
return didContainFormat;
}
CGImageRef osx_CGImageCreateFromFile(std::string filename) {
CGImageRef image = 0;
CFStringRef fileString = 0;
CFURLRef fileURL = 0;
CGImageSourceRef imageSource = 0;
CFDictionaryRef imageSourceOptions = 0;
CFStringRef imageSourceKeys[] = { kCGImageSourceShouldAllowFloat, kCGImageSourceShouldCache };
CFBooleanRef imageSourceValues[] = { kCFBooleanTrue, kCFBooleanTrue };
try {
fileString = CFStringCreateWithCString( kCFAllocatorDefault, filename.c_str(), kCFStringEncodingUTF8 );
if (fileString == 0) throw std::runtime_error("CFStringCreateWithCString");
fileURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, fileString, kCFURLPOSIXPathStyle, 0);
if (fileURL == 0) throw std::runtime_error("CFURLCreateWithFileSystemPath");
imageSource = CGImageSourceCreateWithURL(fileURL, 0);
if (imageSource == 0) throw std::runtime_error("CGImageSourceCreateWithURL");
imageSourceOptions = CFDictionaryCreate( kCFAllocatorDefault, (const void**)&imageSourceKeys, (const void**)&imageSourceValues, 1, 0, 0 );
if (imageSourceOptions == 0) throw std::runtime_error("CFDictionaryCreate");
image = CGImageSourceCreateImageAtIndex(imageSource, 0, imageSourceOptions);
if (image == 0) throw std::runtime_error("CGImageSourceCreateImageAtIndex");
}
catch(std::runtime_error &problem) {
std::cerr << problem.what() << std::endl;
}
CFRelease(imageSourceOptions);
CFRelease(imageSource);
CFRelease(fileURL);
CFRelease(fileString);
return image;
}
void osx_CGImageCrossCubeToImageCube(CGImageRef source, ImageCube &imageCube) {
size_t x = CGImageGetWidth(source) / 3;
size_t y = CGImageGetHeight(source) / 4;
assert( x == y ); // Images should be square. Could scale to ensure this instead of aborting.
CGRect imageBounds[6] = {0};
imageBounds[0] = CGRectMake(2*x, y, x, y); // +x 1
imageBounds[1] = CGRectMake(0, y, x, y); // -x 0
imageBounds[2] = CGRectMake(x, 2*y, x, y); // -y 2
imageBounds[3] = CGRectMake(x, 0, x, y); // +y 3
imageBounds[4] = CGRectMake(x, y, x, y); // -z 4
imageBounds[5] = CGRectMake(x, 3*y, x, y); // +z 5
imageCube.size = x;
imageCube.bitsPerComponent = CGImageGetBitsPerComponent(source);
imageCube.numComponents = 4;
const size_t bytesPerRow = imageCube.size * imageCube.numComponents * imageCube.bitsPerComponent / 8;
CGImageRef partitions[6] = {0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
for (int i = 0; i < 6; ++i) {
imageCube.image[i].resize( imageCube.size * bytesPerRow );
partitions[i] = CGImageCreateWithImageInRect(source, imageBounds[i]);
CGContextRef imageContext = CGBitmapContextCreate( &imageCube.image[i][0],
imageCube.size, imageCube.size,
imageCube.bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaNoneSkipLast | kCGBitmapFloatComponents );
CGContextSaveGState(imageContext);
// Up Down and Backwards are flipped in the cube cross format
if ( i == 2 || i == 3 || i == 5 ) {
CGContextTranslateCTM(imageContext, imageCube.size, imageCube.size);
CGContextScaleCTM(imageContext, -1.0f, -1.0f);
}
CGContextDrawImage(imageContext, CGRectMake(0, 0, imageCube.size, imageCube.size), partitions[i]);
CGContextRestoreGState(imageContext);
CGContextRelease(imageContext);
CGImageRelease(partitions[i]);
}
CGColorSpaceRelease(colorSpace);
}
Apple and OpenGL 3.0
OS X has never had good OpenGL drivers, by which I mean few bugs, and wide support of current standards. Things have improved over time, but there are clearly still problems.
OpenGL 3.0 promises to clean up and slim down the specification, making it clearer and easier to develop and maintain a standards compliant implementation. I'm holding out hope that the change will help Apple out and the quality of their GL drivers will improve.
Speaking of OpenGL 3.0, I'm hoping that GLSL is being moved out of core, and/or that it's being replaced with something better, namely Cg; I'm tired of dealing with vendor-dependent GLSL bugs.
OpenGL 3.0 promises to clean up and slim down the specification, making it clearer and easier to develop and maintain a standards compliant implementation. I'm holding out hope that the change will help Apple out and the quality of their GL drivers will improve.
Speaking of OpenGL 3.0, I'm hoping that GLSL is being moved out of core, and/or that it's being replaced with something better, namely Cg; I'm tired of dealing with vendor-dependent GLSL bugs.
Tuesday, March 11, 2008
OpenGL Demos
I've written an implementation of Preetham's "A Practical Analytic Model for Daylight", an ambient occlusion demo, a vertex buffer object demo, and a GLSL per-pixel lighting demo, I'll post them soon. Tomorrow I'm going to start on a reflection/refraction demo. I'll likely follow them up with a set of tutorials explaining them in some detail; I'd like to start doing more tutorials.
Thursday, February 7, 2008
shadow2DProj
I'm having some difficulty implementing shadow maps in OpenGL. The Orange Book (section 13.2.3) says that shadow2DProj should return a value that is either 0 or 1. Below is an image of the diffuse term multiplied by the result of the lookup, which clearly is not giving values between 0 and 1. Beyond that, the shadows are much sharper than I had expected. I can imagine some sort of PCF going on, but that still doesn't account for the pale shadows.
I can simply force 0,1 values via the shader, but I'd like to understand what's going on rather than force my expectations onto things.


For completeness, the fragment shader follows.
I can simply force 0,1 values via the shader, but I'd like to understand what's going on rather than force my expectations onto things.


For completeness, the fragment shader follows.
#version 110
varying vec3 frag_Position;
varying vec3 frag_Normal;
varying vec3 frag_LightDirection;
varying vec4 frag_ShadowCoordinate;
uniform sampler2DShadow frag_ShadowMap;
void main()
{
vec3 E =-normalize(frag_Position);
vec3 L = normalize(frag_LightDirection);
vec3 H = normalize(E + L);
// Get shadow value
float shadow = shadow2DProj( frag_ShadowMap, frag_ShadowCoordinate ).x;
//if (shadow < 1.0) shadow = 0.0;
// Light properties
const vec3 light_ads = vec3( 0.0, 1.0, 0.0 );
// Material properties
const vec4 material_adss = vec4( 0.0, 0.5, 0.0, 0.0 );
// Light/Material interaction
const vec3 lightCoefficient = light_ads * material_adss.rgb;
vec3 ambientDiffuseSpecular = vec3( 0.0,
shadow * max(0.0, dot(frag_Normal, L)),
shadow == 0.0 ? 0.0 : pow( max(0.0, dot(frag_Normal, H)), material_adss.a ));
// Ambient, Diffuse, Specular contributions
float shade = dot(lightCoefficient, ambientDiffuseSpecular);
gl_FragColor = vec4( shade * gl_Color.rgb, 1.0 );
}
Subscribe to:
Posts (Atom)