50
Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Embed Size (px)

Citation preview

Page 1: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

95.450195.4501

OpenGL

Odds and Ends

Page 2: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

Odds and EndsOdds and Ends

• A few odds and ends to help with assignment #3 particularly issues that might trip you.

• A bit about blending.• A bit about OpenGL stacks.• A bit about OpenGL shaders.

Generally, things you SHOULD be able to figure out by yourself but might not have.

Page 3: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

95.400295.4002

Transformation

Extensions

Page 4: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• There is a lookAtForObject which can build an entire transformation for you…

• If you need the inverse (for something playing the role of a camera), it might be nice to have a version call lookAtForCamera.

• The next slide provides it… IF YOU NEED IT.

A Useful Addition To TransformationA Useful Addition To Transformation

Page 5: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

//In .h filestatic Transformation lookAtForCamera (const Point &from, const Vector

&direction, const Vector &up, const Vector &alternateUp) ;

//In .cpp fileTransformation Transformation::lookAtForCamera (const Point &from,

const Vector &direction, const Vector &up, const Vector &alternateUp) {//This version returns the same thing as gluLookAt but computes it without using the stack...//Note: up is an approximate yAxis. If it is erroneously directed into the z-direction, use alternateUp instead.Vector zAxis = -direction.normalized ();Vector xAxis = (up.cross (zAxis)).normalized ();if (xAxis.isZero ()) xAxis = (alternateUp.cross (zAxis)).normalized ();Vector yAxis = zAxis.cross (xAxis);Transformation result; //Compute the inverse of rotateToAxes (xAxis, yAxis, zAxis, from) which interpreted as RT means computing T-1R-1.result.set (

xAxis.x, yAxis.x, zAxis.x, 0.0,xAxis.y, yAxis.y, zAxis.y, 0.0,xAxis.z, yAxis.z, zAxis.z, 0.0,-from.x*xAxis.x - from.y*xAxis.y - from.z*xAxis.z,-from.x*yAxis.x - from.y*yAxis.y - from.z*yAxis.z,-from.x*zAxis.x - from.y*zAxis.y - from.z*zAxis.z,1.0);

return result;}

A Useful Addition To TransformationA Useful Addition To Transformation

Page 6: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

95.400295.4002

Blending

Page 7: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

Many Effect Require Blending TechniquesMany Effect Require Blending Techniques

• Blending permits the colors of a texture to be merged with the colors already drawn on the back buffer.

• To use it, must enable it; disable when done.

glEnable (GL_BLEND);glDisable (GL_BLEND);

Page 8: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

Must Specify Which Blending Factors To UseMust Specify Which Blending Factors To Use

result = SourceFactor*S + DestinationFactor*D

S is the input texture (the source)

D is the screen pixel (the destination orwhat’s already there)

15 factors available: can get by with 3 or 4.15 factors available: can get by with 3 or 4.

glBlendFunc (sourceFactor, destinationFactor);

coming up1. Example Factors, 2. Example Blend functions

Page 9: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

What’s The Complete Set of Factors?What’s The Complete Set of Factors?

• GL_ZERO 0• GL_ONE 1• GL_SRC_COLOR S• GF_DST_COLOR D• GL_SRC_ALPHA a from S• GL_DST_ALPHA a from D• GL_ONE_MINUS_SRC_ALPHA 1-a from S• GL_ONE_MINUS_DST_ALPHA 1-a from

D

Page 10: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

Complete Set...Complete Set...

• GL_ONE_MINUS_SRC_COLOR 1-S• GL_ONE_MINUS_DST_COLOR 1-D

• There are a few additional rules (available through extensions)..

Examples coming upExamples coming up

Page 11: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

What the Blending Factors Apply ToWhat the Blending Factors Apply To

result = SourceFactor*S + DestinationFactor*D

S is the input texture (the source)

D is the screen pixel (the destination orwhat’s already there)

glBlendFunc (sourceFactor, destinationFactor);

• Note that result has no alpha in it once it’s combined.

• Combination applies to R,G,B components independently (each ranges from 0 to 1)…

Page 12: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

Useful Combination 1: BrighteningUseful Combination 1: Brightening

• Take a little from each AND ignore transparency.glBlendFunc (GL_ONE, GL_ONE);

• Consequences:

Result = 1*S + 1*D (clamped to 1 if > 1)

glBlendFunc (sourceFactor, destinationFactor)glBlendFunc (sourceFactor, destinationFactor)

Creates a brightening (whitening) effect…

1 * 0.5 (gray) + 1 * 0.5 (gray) => 1 (white)

Creates a brightening (whitening) effect…

1 * 0.5 (gray) + 1 * 0.5 (gray) => 1 (white)

Page 13: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

Useful Combination 2: Raw TransparencyUseful Combination 2: Raw Transparency

• Use transparency (called alpha blending)glBlendFunc

(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

• Result = a*S + (1- a)*D (clamped to 1 if > 1)

where a is the alpha in the textured color

glBlendFunc (sourceFactor, destinationFactor)glBlendFunc (sourceFactor, destinationFactor)

If a = 0.7 (mostly opaque), get .7S+.3DIf a = 0.7 (mostly opaque), get .7S+.3D

Page 14: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

What Combination Is Like Having Blending Off?What Combination Is Like Having Blending Off?

• Same as usingglBlendFunc (GL_ONE, GL_ZER0);

• Result = 1*S + 0*D = S

So pixel behind is overwritten

glBlendFunc (sourceFactor, destinationFactor)glBlendFunc (sourceFactor, destinationFactor)

Better to say, glDisable (GL_BLEND) instead.Better to say, glDisable (GL_BLEND) instead.

Page 15: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• One that multiplies rather than adds so that white (1) * what is there => stays the samegray (.5) * what is there => goes darkerblack (0) * what is there => black

glEnable (GL_BLEND);glBlendFunc (GL_ZERO, GL_SRC_COLOR);

• Consequences:

Result = 0*S + S*D (clamped to 1 if > 1)

Useful Combination 3: DarkeningUseful Combination 3: Darkening

This simulates MULTIPLY 0.8*0.8=0.64 (darkens)This simulates MULTIPLY 0.8*0.8=0.64 (darkens)

Page 16: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

95.400295.4002

The OpenGL Stack

Page 17: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

Summary: Thinking With the Left To Right ConventionSummary: Thinking With the Left To Right Convention

How to use the stack? NEXTHow to use the stack? NEXT

v * ABC

MATH works from left to right

CBA

growth direction

From most local to most global

The OpenGL Stack works from right to left

So push C; mult B; mult A; pop

Page 18: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

How Do I Put Something On The StackHow Do I Put Something On The Stack

• Want to translate by T = [tx, ty, tz], and scale by S = [sx, sy, sz].

glMatrixMode (GL_MODELVIEW_MATRIX);glPushMatrix ();

glTranslated (tx, ty, tz);glScaled (sx, sy, sz);

glPopMatrix ();

This puts S*T*whateverIsAlreadyThere on the stack (since it works from right to left)

This puts S*T*whateverIsAlreadyThere on the stack (since it works from right to left)

If W transforms a vehicle to a place in the world with camera C, the stack should contain W * C-1

If W transforms a vehicle to a place in the world with camera C, the stack should contain W * C-1

Page 19: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

95.400295.4002

Shaders

Page 20: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• If a shader uses a texture variable called “birdTexture” via

uniform sampler2D birdTexture

• How does the game engine know what texture to use; e.g.,

texture called “turkey”

Questions YOU Should Have Had In Your MindQuestions YOU Should Have Had In Your Mind

Generally, stuff explained in Shader::example ()

Page 21: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Explain how the ambient occlusion demo does all this.

• Relate how this is different in the engine…

How The Explanation Will GoHow The Explanation Will Go

Page 22: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• A host of routines are used with names that are synonyms…

glCreateProgram versus glCreateProgramObjectARB

glUseProgram versus glUseProgramObjectARB

glUniform1i versus glUniform1iARB

AsideAside

Page 23: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

95.400295.4002

How The Ambient

Occlusion Demo

Connects shaders with

their textures

Page 24: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

//GettingglGenTextures (1, &textureHandle);shaderProgramHandle = glCreateProgram ();

//DeletingglDeleteTextures (1, &textureHandle);glDeleteProgram (shaderProgramHandle);

//UsingglBindTexture (GL_TEXTURE_2D, textureHandle);

or glBindTexture (GL_TEXTURE_RECTANGLE, textureHandle);glUseProgram (shaderProgramHandle);

Everything done via handlesEverything done via handles

For coordinates in range 0..799

0 means “don’t use a shader”

Page 25: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

//Uploading textures (MESSY)

• glBindTexture (GL_TEXTURE_2D, textureHandle);

• Supply a host of sampling information; e.g. GL_CLAMP versus GL_REPEAT

• Upload the bits to the card… viaglTexImage2D or gluBuild2DMipmaps

Everything done via handlesEverything done via handles

AO Demo has no bits to upload, only game engine which also provides a Texture object to do it all.

Page 26: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

//Uploading shaders (MESSY)

• Compile vertex shader, compile pixel shader.

• shaderProgramHandle = glCreateProgram ();

• Attach the shaders to the program.

• Link the program

Everything done via handlesEverything done via handles

AO Demo provides their code for doing this; game engine provides a Shader object for doing this.

Page 27: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

//Connecting shader samplers to textures

In shader “lesterLightingDiffuse” uniform sampler2D texture;

After creating the shader (do this once)glUseProgram (shaderProgramHandle);glUniform1i ("texture", 0); //a texture unit

When you want to draw with a shaderglUseProgram (shaderProgramHandle);

glActiveTexture (GL_TEXTURE0);glBindTexture (GL_TEXTURE_2D, textureHandle);

ORglBindTexture (GL_TEXTURE_RECTANGLE,

textureHandle);

What You Wanted To KnowWhat You Wanted To Know

0, 1, 2, 3, …

For coordinates in range 0..799

Page 28: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Create via handles

glGenFramebuffers (howMany, frameBufs);Plus code to create z-buffer and textures to draw into and code to attach to frame buffer

•Delete via handles

glDeleteFramebuffers (howMany, frameBufs);

•Activate via handles

glBindFramebuffer (GL_FRAMEBUFFER, frameBufs[i]);OR

glBindFramebuffer (GL_FRAMEBUFFER, 0);

FrameBuffers Are The SAMEFrameBuffers Are The SAME

This means now draw into backbuffer

Only AO used frame buffers

Page 29: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

95.400295.4002

How The Engine

Differs From The AO Demo

Page 30: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Has texture and shader objects do some work.• Texture provides

test = Texture::read (“turkey”)//Creates handle + path, reads it

texture->load (mipmapping, forceClamp)//Defaults to true, false (to upload onto

card)

activate ()//To bind to the correct texture handle

• Shader provides

activate ()//To bind to the correct program handle

The EngineThe Engine

Page 31: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Shaders are a recent introduction that were meant to be specified in level file “castle4.wrl”. The start of the file contain the list of shaders used

Shaders: 0; //currentlyShader 1 nameShader 2 name …

• A shader manager keeps track of the shaders which it associates with an object and the terrain via a shader index… Each object including the terrain has a property

"shader" => "-1“ //-1 means no shader

Some Things That Can Cause ProblemsSome Things That Can Cause Problems

Page 32: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• It creates a default shader viadefaultShaderIndex = addShader ("lesterlightingDiffuse");

• When a object is imported, it executes

if (shaderIndex == -1) shaderIndex = defaultShaderIndex;

• When the terrain is imported, it executes //if (shaderIndex == -1) shaderIndex = defaultShaderIndex;

When the Shader Manager is SetupWhen the Shader Manager is Setup

Please UNCOMMENT THIS LINE

Page 33: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• When drawing an object (the castle) or the terrain, it

activates the shader to useactivates the texture to use

• But it fails to executeglActiveTexture (GL_TEXTURE0);

BECAUSE IT DOES THIS ONCE WHEN OPENGL IS SET UP AND ASSUMES IT’S STILL TRUE…

The AO Demo code switches all over the place…

How Else Does It WorkHow Else Does It Work

Page 34: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• What strategy did I use?• Create one file “ssao.cpp” containing all the

ambient occlusion code and comment out stuff not needed.

• Add it to the “physicsForStudent” project including the AO shaders.

• Find a spot in “game.cpp” to call “WilfDisplay”.

• Find a spot in “ssao.cpp” to invoke “world->draw ()”

• Find a spot in “ssao.cpp” to blend AO with what game engine already drew…

Making Ambient Occlusion Work With The EngineMaking Ambient Occlusion Work With The Engine

BASIC IDEA: AVOID CHANGING ANYTHING BEFORE IT WORKS.

Page 35: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Create one file “ssao.cpp” containing the contents of the ambient occlusion file “main.cpp”, “wilfMain.cpp”, and the routines that compile the shader. Add to project.

• Copied over the ambient occlusion shaders into a subdirectory of shaders and called it “AOshaders”.Changes lines from old locations to new

“./src/shaders/ortho.vert” //OLD“../shaders/aoshaders/ortho.vert” //NEW

• Edited each shader so that the first line was#version 120

More Detail StepsMore Detail Steps

Page 36: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Fixed the "glew" problem by uncommenting "#include glew.h", commenting out 2 redeclaration error messages, and moving "glewInit" to spot after call to "setupOpenGL ()".

• Much later, I found out that I would crash in routine glBindFragDataLocation (how ssao routine binds a texture to a texture unit) but that it would work if I added EXT to the routine… INSTEAD, added the following after "#include glew.h",

#undef glBindFragDataLocation

#define glBindFragDataLocation glBindFragDataLocationEXT

Making Ambient Occlusion Work With The EngineMaking Ambient Occlusion Work With The Engine

Page 37: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• There were 3 places in ssao.cpp file that draws quads. Not all of them were drawing counterclockwise (it matters because face culling now has to be on)…

Making Ambient Occlusion Work With The EngineMaking Ambient Occlusion Work With The Engine

glBegin(GL_QUADS);//glVertex2d(0, 0);//glVertex2d(0, size);//glVertex2d(size, size);//glVertex2d(size, 0);glVertex2d (0, 0); //WILF: COUNTER-CLOCKWISE SO ALWAYS WORKS.glVertex2d (size, 0);glVertex2d (size, size);glVertex2d (0, size);

glEnd();

Page 38: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Added 2 routines “setupAmbientOcclusion ()” and “wrapupAmbientOcclusion ()” to contain the setup/wrapup code in the ssao.cpp file and called them at the end of “Game::setup ()” and “Game::wrapup ()”

• Also added the following at the end of setupAmbientOcclusion and WilfDisplay…

• Add the following after call to Render2GBuffer.

Making Ambient Occlusion Work With The EngineMaking Ambient Occlusion Work With The Engine

glBindFramebuffer(GL_FRAMEBUFFER, 0);|glActiveTexture(GL_TEXTURE0);glColor4d (1.0, 1.0, 1.0, 1.0);glUseProgram (0); glDisable (GL_TEXTURE_RECTANGLE);

glEnable (GL_TEXTURE_RECTANGLE);

Used to be permanently

enabled (wrecking normal draws)

Page 39: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Made resolution, near, far, FOV same for both…

Making Ambient Occlusion Work With The EngineMaking Ambient Occlusion Work With The Engine

//glutInitWindowSize (800, 600);glutInitWindowSize (800, 800); //WILF$$ MAKE THE SAME AS AO SHADER

In game engine (main.cpp)

const float zNear = 1.0; //0.1f; //WILF$$ MAKE NEAR AND FAR THE SAME AS ssao.cpp

const float zFar = 2000; //1000.0f; //WILF$$ MAKE NEAR AND FAR THE SAME AS ssao.cpp

const float fov = 40; //65.238f; //WILF$$ MAKE THE SAME AS ENGINE...

In ssao.cpp

Page 40: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

Making Ambient Occlusion Work With The EngineMaking Ambient Occlusion Work With The Engine

//glGetFloatv(GL_MODELVIEW_MATRIX, mVMat); CopyMemory (mVMat, &camera->inverseCameraMatrix.m11,

sizeof (Transformation));

In ssao.cpp (replaced code that was grabbing the model view matrix mVMatfrom the stack by code that gets it from the existing camera objects).

//M3DInvertMatrix44f(mVMat, iMVMat); CopyMemory (iMVMat, &camera->cameraMatrix.m11,

sizeof (Transformation));

Similarly, code that compute the inverse is obtained from the camera

THIS IS AN INVERSE

Page 41: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Assuming the engine draws the world and the ambient occlusion code draws the world, what’s the difference?

The engine wants to draws with the "lesterlightingDiffuse“ shader…

The ssao.cpp code draws with a bunch of different ambient occlusion shaders…

The Most Important Thing To UnderstandThe Most Important Thing To Understand

HOW DO WE MAKE THAT WORK?

Page 42: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

bool disableShaders = false;

void Shader::activate () {extern bool disableShaders; if (disableShaders) return;if (isBroken) {deactivate (); return;}glUseProgramObjectARB (privateProgramHandle);

}

void Shader::deactivate () {extern bool disableShaders; if (disableShaders) return;glUseProgramObjectARB (0);

}

Controlling The GameControlling The Game

Added a global just before void Game::draw () {…}

Changed the routines that activate/deactivate shaders…

Page 43: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

bool disableShaders = false;#define DISABLE disableShaders = true;#define ENABLE disableShaders = false;bool activateAmbientOcclusionBlending = false;

void Game::draw () {//If there is no world, draw a teapot; otherwise, draw the world...//Neither the input manager nor the camera draws itself...enum Choice {AOOnly, NormalOnly, AOThenNormal, NormalThenAO}; Choice choice = NormalThenAO;camera->beginCamera ();

if (world == NULL) { drawTeapots ();

} else {//REVISED PART

}player->draw ();

camera->endCamera ();drawFrameRate ();drawHelp ();

}

REVISED GAME DRAWINGREVISED GAME DRAWING

Page 44: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

activateAmbientOcclusionBlending = choice == NormalThenAO;switch (choice) {

case AOOnly: void WilfDisplay (); DISABLE; WilfDisplay (); break;case NormalOnly: ENABLE; world->draw (); break;case AOThenNormal: DISABLE; WilfDisplay (); ENABLE; world->draw (); break;case NormalThenAO: ENABLE; world->draw (); drawTeapots (); DISABLE; WilfDisplay (); break;

}

REVISED GAME DRAWINGREVISED GAME DRAWING

#define DISABLE disableShaders = true;

#define ENABLE disableShaders = false;

Page 45: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

void DrawModel () {//Used to draw sponza or sibenik models here…//Game engine needs to draw with texture unit 0…glActiveTexture (GL_TEXTURE0); game->world->draw ();

}

void Render2GBuffer () { ….DrawModel();

….}

REVISED ssao.cpp DRAWINGREVISED ssao.cpp DRAWING

Page 46: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Recall: ssao.cpp makes and uses frame buffers to draw with…

• Frame buffers draw into textures. So you never see what they draw on the screen…

• Ultimately, though, it must draw into a back buffer…

• What controls that…

BLENDING AO WITH GAMEBLENDING AO WITH GAME

Page 47: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

void RenderAO (int size, int index) {…extern bool activateAmbientOcclusionBlending;if (size < RESOLUTION) {

glBindFramebuffer(GL_FRAMEBUFFER, frameBufs[index]);glDrawBuffer(GL_COLOR_ATTACHMENT2);

} else {glBindFramebuffer (GL_FRAMEBUFFER, 0);

if (activateAmbientOcclusionBlending) {glEnable (GL_BLEND); glBlendFunc (GL_DST_COLOR,

GL_ZERO); }

}

CODE (NOT SHOWN) TO DRAW ONE QUAD…

if (activateAmbientOcclusionBlending) {glDisable (GL_BLEND); }if (size < RESOLUTION && USE_EXTRA_UPSAMPLING_BLUR) Blur (size,

index);}

What Was The Last Thing Drawn By SSAO.cppWhat Was The Last Thing Drawn By SSAO.cppRUNS IN A LOOP WITH size going from small up to RESOLUTION

LAST ITERATION, size is RESOLUTION

Page 48: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• I did observe a glitch which I assumed was due to the temporal coherence feature. When I rotated continuously, I would sometimes see a dark triangle appear.

• Hacked the code in the shader not to do it...

A GlitchA Glitch

float temporallyBlendedOcclusion (float occlusion) {

return occlusion; //Disabling hack...

return useTemporalSmoothing? occlusion //temporalBlend (...): occlusion;

}

Page 49: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• Since shader “geometry.frag” is computing the normal in camera space and face culling is on, only faces that face the camera will draw... So the normal MUST be pointing in the +z direction...

• If it’s not, make it so...

Found a Fix for the ATI DFDY Instruction BugFound a Fix for the ATI DFDY Instruction Bug

Shader “geometry.frag#version 120#extensionGL_ARB_texture_rectangle : require

in vec4 pos; out vec4 Pos; out vec4 Norm;

void main() {Pos = pos / pos.w;vec3 n = cross (dFdx (pos.xyz), dFdy (pos.xyz));if (n.z < 0.0) n = -n; //If differentials have a bug, fix it..

Norm = vec4 (normalize(n), sign (abs (pos.z)));}

Page 50: Wilf LaLonde @2012 Comp 4501 95.4501 OpenGL Odds and Ends

Wilf LaLonde @2012Comp 4501

• This should convince you that it’s doable…

• Did not try the shadow algorithm… So don’t know if anything is tricky…

ConclusionConclusion